क्यों अभिव्यक्ति 0 <0 == 0 अजगर में झूठी वापसी करता है?


136

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

अगर maxsize0 है तो कतार कभी भरी नहीं है।

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

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

क्या 0 <सत्य अजगर में झूठ के बराबर है?
मैरिनो Marimić

3
@ मेरिनो ćimić: ओपी के प्रश्न में दिखाए गए दूसरे उदाहरण से >>> (0) < (0 == 0), यह स्पष्ट रूप से नहीं है।
मार्टिन्यू

3
एक कारण आपको n = 0 < self.maxsize == self._qsize()किसी भी भाषा में पहली जगह की तरह कोड लिखना नहीं चाहिए । यदि आपकी आँखों को कई बार लाइन में आगे और पीछे डार्ट करना है, तो यह पता लगाने के लिए कि क्या चल रहा है, यह एक अच्छी तरह से लिखी गई लाइन नहीं है। बस इसे कई लाइनों में विभाजित करें।
ब्लूराजा - डैनी पफ्लुघोटे

2
@Blue: मैं इस तरह की तुलना नहीं लिखने से सहमत हूं, लेकिन इसे अलग-अलग लाइनों में विभाजित करना दो तुलनाओं के लिए थोड़ा अलग है। मुझे आशा है कि आपका मतलब है, इसे अलग-अलग तुलनाओं में विभाजित करें। ;)
जेफ मर्काडो

2
@ ब्लैक: मैंने इसे नहीं लिखा, यह पाइथन 2.6 में है। मैं बस समझने की कोशिश कर रहा था कि क्या चल रहा है।
मार्सेलो सांतोस

जवाबों:


113

मेरा मानना ​​है कि पाइथन के पास रिलेशनल ऑपरेटर्स के सीक्वेंस के लिए विशेष केस हैंडलिंग है ताकि रेंज तुलनाओं को व्यक्त करना आसान हो सके। यह कहने के 0 < x <= 5बजाय कहने में सक्षम होने के लिए बहुत अच्छा है (0 < x) and (x <= 5)

इन्हें जंजीर तुलना कहा जाता है । और यह उनके लिए प्रलेखन का एक लिंक है।

अन्य मामलों के बारे में आप बात करते हैं, कोष्ठक एक रिलेशनल ऑपरेटर को दूसरे के सामने लागू करने के लिए मजबूर करता है, और इसलिए वे अब तुलनात्मक रूप से जंजीर नहीं हैं। और चूंकि पूर्णांकों के रूप में आपके पास मान हैं Trueऔर Falseआपको वे उत्तर मिलते हैं जो आप कोष्ठक संस्करणों से बाहर करते हैं।


यह इन तुलनाओं में से कुछ की कोशिश करना और इंट () और बूल () निर्दिष्ट करना दिलचस्प है। मैंने महसूस किया कि किसी भी गैर-शून्य का बूल (1) है। अनुमान है कि मैंने कभी भी बूल (0) या बूल (1) के अलावा किसी अन्य चीज़ को सीधे निर्दिष्ट करने की कोशिश नहीं की होगी, इस विचार के प्रयोग से पहले
j_syk

क्या आपने इसके बजाय इस अनुभाग से लिंक करने का इरादा किया है? docs.python.org/2/reference/expressions.html#comparison
tavnab

@ तवनाब - हाँ। मैं इसे ठीक करने के लिए याद रखने की कोशिश करूँगा। मैं एडिट हिस्ट्री भी चेक करने जा रहा हूं। ऐसा लगता नहीं है कि मैं एक गलती करूँगा। If
ओम्निफेरियस

42

इसलिये

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

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


EDIT - पायथन में ट्रू और फाल्स के बारे में स्पष्टीकरण

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

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

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

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


2
मैंने कलियों के रूप में इस्तेमाल किए जाने वाले बूलियन मूल्यों के लिए एक दिलचस्प उपयोग देखा। अभिव्यक्ति 'success' if result_code == 0 else 'failure'को फिर से लिखा जा सकता है ('error', 'success')[result_code == 0], इससे पहले मैंने कभी किसी सूची / टुपल में किसी आइटम का चयन करने के लिए उपयोग किए गए बूलियन को नहीं देखा था।
एंड्रयू क्लार्क

पायथन 2.2 के आसपास 'बूल' को कुछ समय के लिए जोड़ा गया था।
MRAB

18

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

एक और उदाहरण:

>>> 1 < 5 < 3
False

>>> (1 < 5) < 3
True

1
OMG, OO a < b && b == cकी तरह ही हैa < b == c
किरिल

9
>>> 0 < 0 == 0
False

यह एक जंजीर तुलना है। यह सच है अगर बदले में प्रत्येक जोड़ीदार तुलना सच है। इसके बराबर है(0 < 0) and (0 == 0)

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

यह उसके बराबर है 0 < Trueजो True का मूल्यांकन करता है।

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

यह उसके बराबर है False == 0जो True का मूल्यांकन करता है।

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

समतुल्य 0 < True, जैसा कि ऊपर, सच का मूल्यांकन करता है।


7

Disassembly (बाइट्स कोड) को देखते हुए यह स्पष्ट है कि क्यों 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से अजगर ढेर पर लौटती है ।

अब सूचना पंक्ति ११: JUMP_IF_FALSE_OR_POP 23 इसका अर्थ है कि यदि 0 < 0रिटर्न False२३ पंक्ति की छलांग लगाता है।

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

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

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


क्या यह रिवर्स इंजीनियरिंग एक विशेष कार्यान्वयन के बजाय कल्पना से काम करना आसान नहीं होगा?
डेविड हेफर्नन

नहीं, यह संक्षिप्त उत्तर है। मेरा मानना ​​है कि यह आपके व्यक्तित्व पर निर्भर करता है। यदि आप "ब्लैक बॉक्स" दृश्य से संबंधित हैं और चश्मा और प्रलेखन से अपने उत्तर प्राप्त करना पसंद करते हैं तो यह उत्तर आपको भ्रमित करेगा। यदि आप सामान के आंतरिक भाग को खोदना और प्रकट करना पसंद करते हैं, तो यह उत्तर आपके लिए है। आपकी टिप्पणी कि यह रिवर्स इंजीनियरिंग केवल एक विशेष कार्यान्वयन के लिए प्रासंगिक है, सही है और इसे इंगित किया जाना चाहिए, लेकिन यह इस उत्तर की बात नहीं थी। यह उन लोगों के लिए बहुत आसान है, जो बहुत उत्सुक हैं।
शनि जूल

1
रिवर्स इंजीनियरिंग के साथ समस्या इसकी अनुमानित शक्ति की कमी है। यह एक नई भाषा सीखने का तरीका नहीं है।
डेविड हेफर्नन

एक और चीज जिसे मुझे जोड़ना होगा, वह यह है कि चश्मा और दस्तावेज हमेशा पूरे नहीं होते हैं और ज्यादातर मामलों में ऐसे विशिष्ट मामलों के लिए उत्तर प्रदान नहीं करेंगे। फिर, मेरा मानना ​​है कि किसी को उत्तर तलाशने, जांच करने और गहराई तक पहुंचने में डर नहीं होना चाहिए।
शनि जूल

2

जैसा कि अन्य उल्लेख किया गया x comparison_operator y comparison_operator zहै (x comparison_operator y) and (y comparison_operator z)कि बोनस के साथ सिंथेटिक चीनी है कि केवल एक बार y का मूल्यांकन किया जाता है।

तो आपकी अभिव्यक्ति 0 < 0 == 0वास्तव में है (0 < 0) and (0 == 0), जो मूल्यांकन करता है कि False and Trueकौन सा है False


2

शायद डॉक्स का यह अंश मदद कर सकता है:

ये तथाकथित "समृद्ध तुलना" तरीके हैं, और __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यदि वह किसी दिए गए तर्कों के लिए ऑपरेशन को लागू नहीं करता है। सम्मेलन द्वारा, Falseऔर Trueएक सफल तुलना के लिए लौटाए जाते हैं। हालांकि, ये विधियां किसी भी मूल्य को वापस कर सकती हैं, इसलिए यदि तुलना ऑपरेटर का उपयोग बूलियन संदर्भ में किया जाता है (उदाहरण के लिए, यदि एक बयान की स्थिति में), तो पायथन bool()मूल्य निर्धारित करने के लिए कॉल करेगा कि क्या परिणाम सही है या गलत।

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

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

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

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

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

औपचारिक रूप से, यदि a, b, c, ..., y, z अभिव्यक्ति हैं और op1, op2, ..., opN तुलना संचालक हैं, तो एक op1 b op2 c ... y opN z एक op1 b के बराबर है और b op2 c और ... y opN z, सिवाय इसके कि प्रत्येक अभिव्यक्ति का मूल्यांकन सबसे अधिक बार किया जाता है।


1

यहाँ यह अपनी महिमा में है।

>>> 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
>>> 

0

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

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

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