software - python tutorial




अभिव्यक्ति 0<0== 0 पाइथन में झूठी वापसी क्यों करती है? (6)

Python 2.6 में Queue.py में देखकर, मुझे यह रचना मिली कि मुझे थोड़ा अजीब मिला:

def full(self):
    """Return True if the queue is full, False otherwise
    (not reliable!)."""
    self.mutex.acquire()
    n = 0 < self.maxsize == self._qsize()
    self.mutex.release()
    return n

यदि maxsize 0 है तो कतार कभी पूर्ण नहीं होती है।

मेरा सवाल यह है कि यह इस मामले के लिए कैसे काम करता है? कैसे 0 < 0 == 0 गलत माना जाता है?

>>> 0 < 0 == 0
False
>>> (0) < (0 == 0)
True
>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True

आपके अनुभव का अजीब व्यवहार श्रृंखला की स्थिति के लिए अजगर क्षमता से आता है। चूंकि यह पाता है 0 0 से कम नहीं है, इसलिए यह पूरी अभिव्यक्ति का मूल्यांकन झूठी है। जैसे ही आप अलग-अलग परिस्थितियों में इसे अलग करते हैं, आप कार्यक्षमता बदल रहे हैं। शुरुआत में यह अनिवार्य रूप से परीक्षण कर रहा है कि a < b && b == c आपके मूल विवरण के a < b == c

एक और उदाहरण:

>>> 1 < 5 < 3
False

>>> (1 < 5) < 3
True

इसलिये

(0 < 0) and (0 == 0)

False आप तुलना ऑपरेटर को एक साथ जोड़ सकते हैं और वे स्वचालित रूप से जोड़ी तुलना में विस्तारित हो जाते हैं।

संपादित करें - पाइथन में सही और गलत के बारे में स्पष्टीकरण

पाइथन True एंड False में बस bool उदाहरण हैं, जो int उप-वर्ग है। दूसरे शब्दों में, True वास्तव में केवल 1 है।

इसका मुद्दा यह है कि आप एक पूर्णांक की तरह बूलियन तुलना के परिणाम का उपयोग कर सकते हैं। यह भ्रमित चीजों की तरह होता है

>>> (1==1)+(1==1)
2
>>> (2<1)<1
True

लेकिन ये तभी होंगे जब आप तुलना को संतुलित करते हैं ताकि उनका मूल्यांकन पहले किया जा सके। अन्यथा पायथन तुलना ऑपरेटर का विस्तार करेगा।


डिस्सेप्लर (बाइट कोड) को देखते हुए यह स्पष्ट है कि 0 < 0 == 0 False क्यों है।

यहां इस अभिव्यक्ति का विश्लेषण है:

>>>import dis

>>>def f():
...    0 < 0 == 0

>>>dis.dis(f)
  2      0 LOAD_CONST               1 (0)
         3 LOAD_CONST               1 (0)
         6 DUP_TOP
         7 ROT_THREE
         8 COMPARE_OP               0 (<)
        11 JUMP_IF_FALSE_OR_POP    23
        14 LOAD_CONST               1 (0)
        17 COMPARE_OP               2 (==)
        20 JUMP_FORWARD             2 (to 25)
   >>   23 ROT_TWO
        24 POP_TOP
   >>   25 POP_TOP
        26 LOAD_CONST               0 (None)
        29 RETURN_VALUE

नोटिस लाइन 0-8: ये लाइनें चेक करें कि 0 < 0 जो स्पष्ट रूप से पाइथन स्टैक पर False लौटती है।

अब लाइन 11 पर ध्यान दें: JUMP_IF_FALSE_OR_POP 23 इसका मतलब है कि यदि 0 < 0 लौटाता है तो False पंक्ति 23 पर कूदता है।

अब, 0 < 0 False , इसलिए कूद लिया जाता है, जो एक False साथ ढेर को छोड़ देता है जो पूरे अभिव्यक्ति के लिए वापसी मूल्य 0 < 0 == 0 , भले ही == 0 भाग भी चेक न किया गया हो।

तो, निष्कर्ष निकालने के लिए, उत्तर इस प्रश्न के अन्य उत्तरों में कहा गया है। 0 < 0 == 0 का एक विशेष अर्थ है। कंपाइलर इसका मूल्यांकन दो शर्तों में करता है: 0 < 0 और 0 == 0 । उनके साथ and उनके बीच किसी भी जटिल बुलियन अभिव्यक्ति के साथ, यदि पहली विफल हो जाती है तो दूसरा व्यक्ति भी चेक नहीं किया जाता है।

उम्मीद है कि यह चीजों को थोड़ा सा प्रबुद्ध करता है, और मुझे उम्मीद है कि इस अप्रत्याशित व्यवहार का विश्लेषण करने के लिए मैंने जिस विधि को भविष्य में कोशिश करने के लिए प्रोत्साहित किया है।


मुझे लगता है कि पाइथन जादू के बीच अजीब कर रहा है। 1 < 2 < 3 मतलब है 2 1 और 3 के बीच है।

इस मामले में, मुझे लगता है कि यह कर रहा है [मध्य 0] [बाएं 0] से बड़ा है और [दाएं 0] के बराबर है। मध्य 0 0 बाएं से अधिक नहीं है, इसलिए यह झूठे का मूल्यांकन करता है।


यहां, इसकी सारी महिमा में है।

>>> class showme(object):
...   def __init__(self, name, value):
...     self.name, self.value = name, value
...   def __repr__(self):
...     return "<showme %s:%s>" % (self.name, self.value)
...   def __cmp__(self, other):
...     print "cmp(%r, %r)" % (self, other)
...     if type(other) == showme:
...       return cmp(self.value, other.value)
...     else:
...       return cmp(self.value, other)
... 
>>> showme(1,0) < showme(2,0) == showme(3,0)
cmp(<showme 1:0>, <showme 2:0>)
False
>>> (showme(1,0) < showme(2,0)) == showme(3,0)
cmp(<showme 1:0>, <showme 2:0>)
cmp(<showme 3:0>, False)
True
>>> showme(1,0) < (showme(2,0) == showme(3,0))
cmp(<showme 2:0>, <showme 3:0>)
cmp(<showme 1:0>, True)
True
>>> 

हो सकता है कि docs से यह अंश मदद कर सके:

ये तथाकथित "समृद्ध तुलना" विधियां हैं, और तुलना ऑपरेटर के लिए नीचे __cmp__() प्राथमिकता के लिए कहा जाता है। ऑपरेटर प्रतीकों और विधि नामों के बीच पत्राचार निम्नानुसार है: x<y कॉल x.__lt__(y) , x<=y कॉल x.__le__(y) , x==y कॉल x.__eq__(y) , x!=y और x<>y कॉल x.__ne__(y) , x>y कॉल x.__gt__(y) , और x>=y कॉल x.__ge__(y)

एक समृद्ध तुलना विधि NotImplemented लागू नहीं कर NotImplemented अगर यह किसी दिए गए जोड़ी के लिए ऑपरेशन को लागू नहीं करती है। सम्मेलन से, False और True सफल तुलना के लिए वापस आ गए हैं। हालांकि, ये विधियां किसी भी मूल्य को वापस कर सकती हैं, इसलिए यदि तुलना ऑपरेटर को बूलियन संदर्भ में उपयोग किया जाता है (उदाहरण के लिए, यदि एक कथन की स्थिति में), तो पाइथन मूल्य पर bool() को कॉल करेगा, यह निर्धारित करने के लिए कि परिणाम सही है या गलत है ।

तुलना ऑपरेटर के बीच कोई अंतर्निहित संबंध नहीं हैं। x==y की सच्चाई यह नहीं दर्शाती है कि x!=y गलत है। तदनुसार, __eq__() को परिभाषित करते समय, किसी को भी __ne__() को परिभाषित करना चाहिए ताकि ऑपरेटर अपेक्षित व्यवहार कर सकें। __hash__() ऑब्जेक्ट्स बनाने पर कुछ महत्वपूर्ण नोट्स के लिए __hash__() पर पैराग्राफ देखें जो कस्टम तुलना संचालन का समर्थन करता है और शब्दकोश कुंजी के रूप में प्रयोग योग्य है।

इन विधियों के कोई स्वैप-तर्क संस्करण नहीं हैं (जब बाएं तर्क ऑपरेशन का समर्थन नहीं करता है लेकिन सही तर्क करता है); बल्कि, __lt__() और __gt__() एक-दूसरे के प्रतिबिंब हैं, __le__() और __ge__() एक दूसरे के प्रतिबिंब हैं, और __eq__() और __ne__() उनके स्वयं के प्रतिबिंब हैं।

समृद्ध तुलना विधियों के लिए तर्क कभी भी मजबूर नहीं होते हैं।

ये तुलना थीं लेकिन चूंकि आप तुलना कर रहे हैं, आपको पता होना चाहिए कि:

तुलना मनमाने ढंग से जंजीर की जा सकती है, उदाहरण के लिए, x < y <= z x < y and y <= z बराबर है, सिवाय इसके कि y का मूल्यांकन केवल एक बार किया जाता है (लेकिन दोनों मामलों में z का मूल्यांकन नहीं किया जाता है जब x <y पाया जाता है झूठी होने के लिए)।

औपचारिक रूप से, यदि ए, बी, सी, ..., वाई, जेड अभिव्यक्तियां और op1, op2, ... हैं, ओपीएन तुलना ऑपरेटर हैं, फिर एक ओपी 1 बी op2 c ... y opn z op1 b के बराबर है और बी op2 सी और ... y opn z, सिवाय इसके कि प्रत्येक अभिव्यक्ति का मूल्यांकन सबसे अधिक बार किया जाता है।





python