गैर-बूलियन मूल्यों के साथ "और" और "या" कैसे कार्य करते हैं?


97

मैं अजगर को सीखने की कोशिश कर रहा हूं और कुछ ऐसे कोड आए हैं जो अच्छे और छोटे हैं लेकिन पूरी तरह से समझ में नहीं आते हैं

संदर्भ था:

def fn(*args):
    return len(args) and max(args)-min(args)

मुझे वह मिल रहा है जो वह कर रहा है, लेकिन अजगर ऐसा क्यों करता है - यानी ट्रू / फाल्स के बजाय वैल्यू लौटाता है?

10 and 7-2

रिटर्न 5. इसी तरह, बदलने और करने के लिए या कार्यक्षमता में परिवर्तन का परिणाम देगा। इसलिए

10 or 7 - 2

10 लौटेगा।

क्या यह कानूनी / विश्वसनीय शैली है, या इस पर कोई गौण हैं?


1
and(साथ ही or) बूलियन मूल्यों के साथ काम करने या लौटने के लिए प्रतिबंधित नहीं है।
cs95

1
IMNSHO: यह लिखने का एक कुछ भ्रमित करने वाला तरीका है; मैं यह नहीं बता सकता कि अगर यह बूलियन लौटाना है (क्या एक अलग न्यूनतम और अधिकतम है) या एक संख्या (न्यूनतम और अधिकतम का अंतर क्या है)। यदि बाद वाला है, तो यह सवाल भी है कि क्या यह शून्य-लंबाई सूची के अंतर को एक संख्या के रूप में देने के लिए कोई मतलब है। ( Noneया एक अपवाद के बजाय )
ilkachachu

7
यह काम करता है, जैसा कि अन्य लोगों ने समझाया है, हालांकि एक संभावित मुद्दा यह है कि अगर यह रिटर्न देता है 0तो आप यह नहीं बता सकते कि क्या argsखाली था या गैर-खाली था लेकिन सभी तत्व समान थे।
विशेष रूप से लाइम

@ ईस्पेक्टाइम: बिल्कुल। मैंने अपने उत्तर में इसका उल्लेख किया है ।
एरिक डुमिनील

जवाबों:


135

टी एल; डॉ

हम दो तार्किक ऑपरेटरों के दो व्यवहार को सारांशित करके शुरू करते हैं andऔर or। ये मुहावरे हमारी चर्चा का आधार बनेंगे।

and

पहला फल्सी मान लौटाएं यदि कोई हैं, तो अभिव्यक्ति में अंतिम मान लौटाएं।

or

पहला सत्य मान लौटाएं यदि कोई हो, और अभिव्यक्ति में अंतिम मान लौटाएं।

व्यवहार को भी डॉक्स में संक्षेप में प्रस्तुत किया गया है , विशेष रूप से इस तालिका में:

यहां छवि विवरण दर्ज करें

केवल ऑपरेटर अपने ऑपरेटर की परवाह किए बिना एक बूलियन मान लौटाता है not


"सत्यता", और "सत्य" मूल्यांकन

बयान

len(args) and max(args) - min(args)

एक है बहुत pythonic संक्षिप्त (और यकीनन कम पठनीय) और कहा कि "अगर के रास्ते argsखाली नहीं है, का परिणाम लौटने max(args) - min(args)", अन्यथा वापसी 0। सामान्य तौर पर, यह एक if-elseअभिव्यक्ति का अधिक संक्षिप्त प्रतिनिधित्व है । उदाहरण के लिए,

exp1 and exp2

को (मोटे तौर पर) अनुवाद करना चाहिए:

r1 = exp1
if r1:
    r1 = exp2

या, समकक्ष,

r1 = exp1 if exp1 else exp2

इसी तरह,

exp1 or exp2

के बराबर है,

r1 = exp1
if not r1:
    r1 = exp2

कहाँ exp1और exp2मनमानी अजगर वस्तुओं, या कुछ वस्तु लौटाने वाले भाव हैं। यहां तार्किक andऔर orऑपरेटरों के उपयोग को समझने की कुंजी यह समझ रही है कि वे बूलियन मूल्यों को संचालित करने या वापस करने के लिए प्रतिबंधित नहीं हैं। सत्यता मूल्य वाली किसी भी वस्तु का परीक्षण यहाँ किया जा सकता है। यह भी शामिल है int, str, list, dict, tuple, set, NoneType, और उपयोगकर्ता परिभाषित वस्तुओं। लघु परिपालन नियम अभी भी लागू होते हैं।

लेकिन सच्चाई क्या है?
यह संदर्भित करता है कि सशर्त अभिव्यक्तियों में उपयोग किए जाने पर वस्तुओं का मूल्यांकन कैसे किया जाता है। @ पैट्रिक हाउ ने इस पोस्ट में सच्चाई को संक्षेप में प्रस्तुत किया है ।

निम्नलिखित को छोड़कर सभी मूल्यों को "सत्य" माना जाता है, जो "मिथ्या" हैं:

  • None
  • False
  • 0
  • 0.0
  • 0j
  • Decimal(0)
  • Fraction(0, 1)
  • [] - एक खाली list
  • {} - एक खाली dict
  • () - एक खाली tuple
  • '' - एक खाली str
  • b'' - एक खाली bytes
  • set() - एक खाली set
  • एक खाली range, जैसेrange(0)
  • जिसके लिए वस्तुएं
    • obj.__bool__() रिटर्न False
    • obj.__len__() रिटर्न 0

एक "सत्य" मूल्य चेक ifया while स्टेटमेंट द्वारा किए गए चेक को संतुष्ट करेगा । हम "सत्य" और "मिथ्या" का उपयोग boolमूल्यों Trueऔर अंतर से अलग करने के लिए करते हैं False


कैसे andकाम करता है

हम ओपी के प्रश्न पर एक चर्चा के रूप में चर्चा करते हैं कि इन उदाहरणों में ये ऑपरेटर कैसे हैं।

परिभाषा के साथ एक फ़ंक्शन दिया

def foo(*args):
    ...

मैं शून्य या अधिक तर्कों की सूची में न्यूनतम और अधिकतम मूल्य के बीच के अंतर को कैसे वापस करूं?

न्यूनतम और अधिकतम खोजना आसान है (इनबिल्ट फ़ंक्शन का उपयोग करें!)। यहां एकमात्र स्नैग उचित रूप से कोने के मामले को संभाल रहा है जहां तर्क सूची खाली हो सकती है (उदाहरण के लिए, कॉलिंग foo())। हम andऑपरेटर की बदौलत दोनों को एक पंक्ति में कर सकते हैं :

def foo(*args):
     return len(args) and max(args) - min(args)

foo(1, 2, 3, 4, 5)
# 4

foo()
# 0

चूंकि andउपयोग किया जाता है, दूसरी अभिव्यक्ति का मूल्यांकन भी किया जाना चाहिए यदि पहला है True। ध्यान दें, यदि पहली अभिव्यक्ति का मूल्यांकन सत्य है, तो वापसी मूल्य हमेशा दूसरी अभिव्यक्ति का परिणाम होता है । यदि पहली अभिव्यक्ति का मूल्यांकन फल्सी होने के लिए किया जाता है, तो लौटाया गया परिणाम पहली अभिव्यक्ति का परिणाम है।

उपरोक्त फ़ंक्शन में, यदि fooएक या अधिक तर्क प्राप्त होते हैं, len(args)तो 0(एक सकारात्मक संख्या) से अधिक है , इसलिए लौटाया गया परिणाम है max(args) - min(args)। OTOH, अगर कोई तर्क पारित कर रहे हैं, len(args)है 0जो Falsy है, और 0दिया जाता है।

ध्यान दें कि इस फ़ंक्शन को लिखने का एक वैकल्पिक तरीका होगा:

def foo(*args):
    if not len(args):
        return 0

    return max(args) - min(args)

या, अधिक संक्षेप में,

def foo(*args):
    return 0 if not args else max(args) - min(args)

यदि निश्चित रूप से, इनमें से कोई भी कार्य किसी भी प्रकार की जाँच नहीं करता है, तो जब तक आप प्रदान किए गए इनपुट पर पूरी तरह से भरोसा नहीं करते हैं , तब तक इन निर्माणों की सादगी पर भरोसा न करें


कैसे orकाम करता है

मैं orएक समान उदाहरण के साथ एक समान फैशन में काम करने की व्याख्या करता हूं ।

परिभाषा के साथ एक फ़ंक्शन दिया

def foo(*args):
    ...

आप fooसभी नंबरों को वापस करने के लिए कैसे पूरा करेंगे 9000?

हम orयहां कोने के मामले को संभालने के लिए उपयोग करते हैं। हम इस fooरूप में परिभाषित करते हैं:

def foo(*args):
     return [x for x in args if x > 9000] or 'No number over 9000!'

foo(9004, 1, 2, 500)
# [9004]

foo(1, 2, 3, 4)
# 'No number over 9000!'

fooसभी नंबरों को बनाए रखने के लिए सूची पर एक निस्पंदन करता है 9000। यदि ऐसी कोई संख्या मौजूद है, तो सूची की समझ का नतीजा एक गैर-रिक्त सूची है, जो सत्य है, इसलिए इसे वापस कर दिया जाता है (यहां कार्रवाई में छोटी चक्कर लगाना)। यदि ऐसी कोई संख्या मौजूद नहीं है, तो सूची COMP का परिणाम []गलत है। तो अब दूसरी अभिव्यक्ति का मूल्यांकन किया जाता है (एक गैर-रिक्त स्ट्रिंग) और वापस किया जाता है।

सशर्त का उपयोग करते हुए, हम इस फ़ंक्शन को फिर से लिख सकते हैं,

def foo(*args):
    r = [x for x in args if x > 9000]
    if not r:
        return 'No number over 9000!' 

    return r

पहले की तरह, यह संरचना त्रुटि से निपटने के मामले में अधिक लचीली है।


33
यह संक्षिप्तता के लिए सभी स्पष्टता का त्याग करने के लिए "पायथोनिक" नहीं है, जो मुझे लगता है कि यहां मामला है। यह एक सीधा निर्माण नहीं है।
डीबीड्रेनको

11
मुझे लगता है कि एक को ध्यान देना चाहिए कि पायथन सशर्त अभिव्यक्तियों ने इस वाक्य रचना को कम आम बना दिया है। मैं निश्चित रूप से अधिकतम (आर्ग्स) - मिनट (आर्ग्स) को पसंद करता हूं, अगर लेन (आर्ग्स) बाकी 0 मूल के लिए।
रिचर्डब

3
एक और आम है जो पहले भ्रमित कर रहा है, एक मान दे रहा है यदि कोई मौजूद नहीं है: "some_var = arg या 3"
Erik

12
@ बाल्ड्रिक से पहले लोग टर्नरी ऑपरेटरों के पक्ष में इस वाक्य रचना को कोसना शुरू करते हैं, ध्यान रखें कि जब यह एन-आर्य स्थिति अभिव्यक्तियों की बात आती है, तो टर्नेरी ऑपरेटर जल्दी से हाथ से निकल सकते हैं। उदाहरण के लिए, if ... else (if ... else (if ... else (if ... else ...)))बस के रूप में के रूप में अच्छी तरह से फिर से लिखा जा सकता है ... and ... and ... and ... and ...और उस बिंदु पर यह वास्तव में किसी भी मामले के लिए पठनीयता पर बहस करने के लिए कठिन हो जाता है।
cs95

4
यह संक्षिप्तता के लिए स्पष्टता का त्याग करने के लिए अजगर नहीं है, लेकिन यह ऐसा नहीं करता है। यह एक जाना माना मुहावरा है। यह एक मुहावरा है जिसे आपको सीखना है, किसी अन्य मुहावरे की तरह, लेकिन यह शायद ही 'स्पष्टता का त्याग' है।
माइल्स राउत

18

पायथन डॉक्स से उद्धरण

ध्यान दें कि न तो मान को प्रतिबंधित करें andऔर न ही वे टाइप करें और वे वापस लौटें और बल्कि अंतिम मूल्यांकित तर्क लौटाएं । यह कभी-कभी उपयोगी होता है, उदाहरण के लिए, यदि एक स्ट्रिंग है जिसे डिफ़ॉल्ट मान द्वारा प्रतिस्थापित किया जाना चाहिए यदि यह खाली है, तो अभिव्यक्ति वांछित मूल्य प्राप्त करती है।or FalseTruess or 'foo'

तो, यह है कि पायथन को बूलियन अभिव्यक्तियों का मूल्यांकन करने के लिए कैसे बनाया गया था और उपरोक्त प्रलेखन हमें एक अंतर्दृष्टि देता है कि उन्होंने ऐसा क्यों किया।

एक बूलियन मूल्य प्राप्त करने के लिए बस इसे टाइप करें।

return bool(len(args) and max(args)-min(args))

क्यों?

लघु सर्किटिंग।

उदाहरण के लिए:

2 and 3 # Returns 3 because 2 is Truthy so it has to check 3 too
0 and 3 # Returns 0 because 0 is Falsey and there's no need to check 3 at all

वही इसके लिए orभी जाता है, अर्थात् , यह अभिव्यक्ति को लौटा देगा जो सत्य है जैसे ही यह पता चलता है, क्योंकि बाकी अभिव्यक्ति का मूल्यांकन निरर्थक है।

इसके बजाय कट्टर लौटने का Trueया False, अजगर रिटर्न Truthy या Falsey है, जो वैसे भी करने के लिए मूल्यांकन करने के लिए जा रहे हैं Trueया False। आप के रूप में अभिव्यक्ति का उपयोग कर सकते हैं, और यह अभी भी काम करेगा।


सत्य और असत्य क्या है, यह जानने के लिए पैट्रिक हॉ का जवाब देखें


7

और और या बूलियन तर्क करते हैं, लेकिन वे वास्तविक मान जब वे तुलना कर रहे हैं में से एक वापस जाएँ। उपयोग करते समय और , मान का मूल्यांकन बूलियन संदर्भ में बाएं से दाएं किया जाता है। 0, '', [], (), {}, और बूलियन संदर्भ में कोई भी गलत नहीं है; बाकी सब सच है।

यदि बूलियन संदर्भ में सभी मान सत्य हैं, और अंतिम मान लौटाता है।

>>> 2 and 5
5
>>> 2 and 5 and 10
10

यदि कोई मूल्य बूलियन संदर्भ में गलत है और पहला गलत मान लौटाता है।

>>> '' and 5
''
>>> 2 and 0 and 5
0

तो कोड

return len(args) and max(args)-min(args)

max(args)-min(args)जब args का मान लौटाता है तो वह वापस लौटता है len(args)जो 0 है।


5

क्या यह कानूनी / विश्वसनीय शैली है, या इस पर कोई गौण हैं?

यह वैध है, यह एक शॉर्ट सर्किट मूल्यांकन है जहां अंतिम मान लौटाया जाता है।

आप एक अच्छा उदाहरण प्रदान करते हैं। 0यदि कोई तर्क पारित नहीं होता है, तो फ़ंक्शन वापस आ जाएगा , और कोड को बिना किसी तर्क के विशेष मामले की जांच करने की आवश्यकता नहीं है।

इसका उपयोग करने का एक और तरीका है, एक खाली सूची की तरह, कोई भी किसी भी प्रकार के तर्कों को डिफ़ॉल्ट नहीं कर सकता है:

def fn(alist=None):
    alist = alist or []
    ....

अगर कुछ गैर-सत्य मान इसे पास कर दिया जाता है, alistतो खाली सूची में चूक, एक ifबयान से बचने का आसान तरीका और परस्पर विरोधी तर्क गड्ढे में गिरना


3

gotchas

हां, थोड़े-थोड़े गॅच हैं।

fn() == fn(3) == fn(4, 4)

सबसे पहले, यदि fnरिटर्न 0, तो आप यह नहीं जान सकते हैं कि क्या यह बिना किसी पैरामीटर के, एक पैरामीटर के साथ या एकाधिक, समान मापदंडों के साथ बुलाया गया था:

>>> fn()
0
>>> fn(3)
0
>>> fn(3, 3, 3)
0

क्या fnमतलब है?

फिर, पायथन एक गतिशील भाषा है। यह कहीं भी निर्दिष्ट नहीं है कि क्या fnकरता है, इसका इनपुट क्या होना चाहिए और इसका आउटपुट कैसा दिखना चाहिए। इसलिए, फ़ंक्शन को सही ढंग से नाम देना वास्तव में महत्वपूर्ण है। इसी तरह, तर्कों को बुलाया नहीं जाना चाहिए argsdelta(*numbers)या calculate_range(*numbers)बेहतर वर्णन कर सकता है कि फ़ंक्शन क्या करना चाहिए।

तर्क की त्रुटियाँ

अंत में, तार्किक andऑपरेटर को यह माना जाता है कि यदि किसी तर्क के बिना फ़ंक्शन को विफल करने से रोका जाए। यह अभी भी विफल रहता है अगर कुछ तर्क एक संख्या नहीं है, हालांकि:

>>> fn('1')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in fn
TypeError: unsupported operand type(s) for -: 'str' and 'str'
>>> fn(1, '2')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in fn
TypeError: '>' not supported between instances of 'str' and 'int'
>>> fn('a', 'b')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in fn
TypeError: unsupported operand type(s) for -: 'str' and 'str'

संभव विकल्प

यहाँ "अनुमति की तुलना में माफी माँगने में आसान" के अनुसार फ़ंक्शन लिखने का एक तरीका है । सिद्धांत :

def delta(*numbers):
    try:
        return max(numbers) - min(numbers)
    except TypeError:
        raise ValueError("delta should only be called with numerical arguments") from None
    except ValueError:
        raise ValueError("delta should be called with at least one numerical argument") from None

उदहारण के लिए:

>>> delta()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in delta
ValueError: delta should be called with at least one numerical argument
>>> delta(3)
0
>>> delta('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in delta
ValueError: delta should only be called with numerical arguments
>>> delta('a', 'b')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in delta
ValueError: delta should only be called with numerical arguments
>>> delta('a', 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in delta
ValueError: delta should only be called with numerical arguments
>>> delta(3, 4.5)
1.5
>>> delta(3, 5, 7, 2)
5

क्या तुम सच में एक अपवाद जब बढ़ाने के लिए नहीं करना चाहते हैं deltaकिसी भी तर्क के बिना कहा जाता है, तो आप कुछ मूल्य है जो अन्यथा संभव नहीं हो सकता है लौट सकते हैं (उदाहरण के लिए -1या None):

>>> def delta(*numbers):
...     try:
...         return max(numbers) - min(numbers)
...     except TypeError:
...         raise ValueError("delta should only be called with numerical arguments") from None
...     except ValueError:
...         return -1 # or None
... 
>>> 
>>> delta()
-1

0

क्या यह कानूनी / विश्वसनीय शैली है, या इस पर कोई गौण हैं?

मैं इस सवाल में जोड़ना चाहूंगा कि यह न केवल वैध और विश्वसनीय है बल्कि यह अल्ट्रा व्यावहारिक भी है। ये रहा एक सरल उदाहरण:

>>>example_list = []
>>>print example_list or 'empty list'
empty list

इसलिए आप वास्तव में अपने लाभ पर इसका उपयोग कर सकते हैं। यह कैसे मैं इसे देख रहा हूं:

Or ऑपरेटर

पायथन का orऑपरेटर पहला ट्रुथ-वाई मान या अंतिम मान लौटाता है, और रुक जाता है

And ऑपरेटर

पायथन का andऑपरेटर पहला गलत-y मान या अंतिम मान लौटाता है, और रुक जाता है

परदे के पीछे

अजगर में, True0. को छोड़कर सभी संख्याओं की व्याख्या की जाती है , इसलिए:

0 and 10 

के समान है:

False and True

जो स्पष्ट रूप से है False। इसलिए यह तर्कसंगत है कि यह 0 देता है


0

हाँ। यह तुलना और व्यवहार का सही व्यवहार है।

अजगर में कम से कम, A and Bरिटर्न Bअगर Aअनिवार्य रूप से किया जाता है Trueशामिल हैं, अगर Aनहीं अशक्त, नहीं है Noneनहीं एक खाली कंटेनर (जैसे एक खाली के रूप में list, dict, आदि)। Aलौटा है IFF Aअनिवार्य रूप से Falseया हैNone या रिक्त या रिक्त है।

दूसरी ओर, A or Bरिटर्न Aअगर Aअनिवार्य रूप से किया जाता है Trueशामिल हैं, अगर Aनहीं अशक्त, नहीं है Noneनहीं एक खाली कंटेनर (जैसे एक खाली के रूप में list, dict, आदि), अन्यथा यह रिटर्नB

इस व्यवहार को नोटिस (या अनदेखी करना) आसान नहीं है क्योंकि, पायथन में, कोई भी non-null ट्रू का मूल्यांकन करने वाली गैर-रिक्त वस्तु को बूलियन की तरह माना जाता है।

उदाहरण के लिए, सभी निम्नलिखित "ट्रू" प्रिंट करेंगे

if [102]: 
    print "True"
else: 
    print "False"

if "anything that is not empty or None": 
    print "True"
else: 
    print "False"

if {1, 2, 3}: 
    print "True"
else: 
    print "False"

दूसरी ओर, सभी निम्नलिखित "गलत" छापेंगे

if []: 
    print "True"
else: 
    print "False"

if "": 
    print "True"
else: 
    print "False"

if set ([]): 
    print "True"
else: 
    print "False"

धन्यवाद। मैं लिखना चाहता था Aअनिवार्य रूप से है True। सही किया।
इमैनुएलसा

0

सरल तरीके से समझने के लिए,

तथा : if first_val is False return first_val else second_value

उदाहरण के लिए:

1 and 2 # here it will return 2 because 1 is not False

परंतु,

0 and 2 # will return 0 because first value is 0 i.e False

और => यदि कोई झूठा है, तो वह झूठा होगा। यदि दोनों सत्य हैं तो केवल सत्य बनेंगे

या: if first_val is False return second_val else first_value

कारण यह है कि यदि पहला गलत है, तो जांच लें कि 2 सही है या नहीं।

उदाहरण के लिए:

1 or 2 # here it will return 1 because 1 is not False

परंतु,

0 or 2 # will return 2 because first value is 0 i.e False

या => यदि कोई असत्य है, तो वह सत्य होगा। इसलिए यदि पहला मूल्य गलत है तो कोई बात नहीं कि 2 मान क्या होगा। इसलिए यह दूसरा मूल्य देता है जो कभी भी हो सकता है।

यदि कोई सत्य है तो वह सत्य हो जाएगा। अगर दोनों झूठे हैं तो यह गलत हो जाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.