क्यों पायथन में "0, 0 == (0, 0)" बराबर "(0, गलत)" होता है?


118

पायथन में (मैंने केवल पायथन 3.6 के साथ जाँच की थी, लेकिन मेरा मानना ​​है कि इसे पिछले संस्करणों में से कई के लिए भी पकड़ना चाहिए):

(0, 0) == 0, 0   # results in a two element tuple: (False, 0)
0, 0 == (0, 0)   # results in a two element tuple: (0, False)
(0, 0) == (0, 0) # results in a boolean True

परंतु:

a = 0, 0
b = (0, 0)
a == b # results in a boolean True

परिणाम दो दृष्टिकोणों के बीच भिन्न क्यों है? क्या समानता ऑपरेटर ट्यूल को अलग तरीके से संभालता है?

जवाबों:


156

पहले दो अभिव्यक्तियाँ दोनों तुक के रूप में हैं:

  1. (0, 0) == 0(जो है False), उसके बाद0
  2. 0, उसके बाद 0 == (0, 0)(जो अभी भी Falseउस तरह से चारों ओर है)।

समानता संचालक की तुलना में अल्पविराम विभाजक की सापेक्ष पूर्ववर्तीता के कारण भाव इस तरह विभाजित हो जाते हैं: पायथन एक टपल देखता है जिसमें दो अभिव्यक्तियाँ होती हैं, जिनमें से एक दो टुपल्स के साथ समानता परीक्षण के बजाय एक समानता परीक्षण होता है।

लेकिन आपके दूसरे बयानों में, एक तुक a = 0, 0 नहीं हो सकती। टपल मूल्यों का एक संग्रह है, और एक समानता परीक्षण के विपरीत, असाइनमेंट का पायथन में कोई मूल्य नहीं है। एक असाइनमेंट एक अभिव्यक्ति नहीं है, लेकिन एक बयान है; इसका कोई मूल्य नहीं है जिसे टुप या किसी अन्य आसपास के अभिव्यक्ति में शामिल किया जा सकता है। यदि आपने (a = 0), 0टपल के रूप में व्याख्या को मजबूर करने के लिए कुछ कोशिश की , तो आपको एक सिंटैक्स त्रुटि मिलेगी। यह एक चर के कार्य को छोड़ देता है - जो इसे लिखकर और अधिक स्पष्ट किया जा सकता है a = (0, 0)- केवल मान्य व्याख्या के रूप में a = 0, 0

इसलिए, कोष्ठक के बिना भी a, दोनों के लिए और यह bमान दिया जाता है (0,0), इसलिए ऐसा a == bहै True


17
मैं कहूंगा कि अल्पविराम की समानता समानता से कम है, क्योंकि समानता के मूल्यांकन से पहले अल्पविराम ऑपरेटर: समानता में अल्पविराम ऑपरेटर की तुलना में अधिक पूर्वता है। लेकिन यह हमेशा भ्रम का एक स्रोत है; बस यह बताना चाहता था कि अन्य स्रोत आसपास की चीजों को पलट सकते हैं।
tomsmeding

2
आप यह कहकर कम / उच्च क्रियात्मक भ्रम से बच सकते हैं कि ,तुलना में कम कसकर बांधता है ==
अमलॉयल

4
अल्पविराम एक ऑपरेटर नहीं है docs.python.org/3.4/faq/…
Chris_Rands

48
डॉक्स दावा कर सकते हैं कि सभी चाहते हैं, लेकिन यह कोई फर्क नहीं पड़ता। आप एक पार्सर लिख सकते हैं ताकि हर ऑपरेटर को अपना उत्पादन मिल जाए और कार्यान्वयन में कहीं भी कोई स्पष्ट "पूर्वगामीता" न हो, लेकिन यह उन संक्रियात्मक इकाइयों को ऑपरेटरों से नहीं रखता है। आप "ऑपरेटर" को कुछ कार्यान्वयन-विशिष्ट तरीके से पुनर्परिभाषित कर सकते हैं। , जो कि जाहिरा तौर पर उन्होंने पायथन में किया था, लेकिन इससे शब्द का निहितार्थ नहीं बदला। अल्पविराम प्रभावी रूप से एक ऑपरेटर है जो ट्यूपल्स का उत्पादन करता है। उदाहरण के लिए, इसकी प्रसूति में पता चलता है कि जिस तरह से इसकी सापेक्ष वरीयता कोष्ठकों से प्रभावित होती है।
मार्क रीड

68

आप सभी 3 उदाहरणों में जो देखते हैं, वह भाषा के व्याकरण विनिर्देश का परिणाम है , और स्रोत कोड में सामने आने वाले टोकन को पार्स ट्री बनाने के लिए पार्स किया जाता है।

इस निम्न स्तर के कोड पर एक नज़र डालते हुए आपको यह समझने में मदद करनी चाहिए कि हुड के नीचे क्या होता है। हम इन अजगर बयानों को ले सकते हैं, उन्हें बाइट कोड में बदल सकते हैं और फिर disमॉड्यूल का उपयोग करके उन्हें विघटित कर सकते हैं :

मामला एक: (0, 0) == 0, 0

>>> dis.dis(compile("(0, 0) == 0, 0", '', 'exec'))
  1           0 LOAD_CONST               2 ((0, 0))
              3 LOAD_CONST               0 (0)
              6 COMPARE_OP               2 (==)
              9 LOAD_CONST               0 (0)
             12 BUILD_TUPLE              2
             15 POP_TOP
             16 LOAD_CONST               1 (None)
             19 RETURN_VALUE

(0, 0)पहले की तुलना में 0सबसे पहले है और इसका मूल्यांकन किया जाता है False। तब इस परिणाम के साथ एक ट्यूपल का निर्माण किया जाता है 0, इसलिए आप प्राप्त करते हैं (False, 0)

केस 2: 0, 0 == (0, 0)

>>> dis.dis(compile("0, 0 == (0, 0)", '', 'exec'))
  1           0 LOAD_CONST               0 (0)
              3 LOAD_CONST               0 (0)
              6 LOAD_CONST               2 ((0, 0))
              9 COMPARE_OP               2 (==)
             12 BUILD_TUPLE              2
             15 POP_TOP
             16 LOAD_CONST               1 (None)
             19 RETURN_VALUE

0पहले तत्व के रूप में एक टपल का निर्माण किया जाता है। दूसरे तत्व के लिए, पहले मामले की तरह ही जांच की जाती है और मूल्यांकन किया जाता है False, इसलिए आप प्राप्त करते हैं (0, False)

केस 3: (0, 0) == (0, 0)

>>> dis.dis(compile("(0, 0) == (0, 0)", '', 'exec'))
  1           0 LOAD_CONST               2 ((0, 0))
              3 LOAD_CONST               3 ((0, 0))
              6 COMPARE_OP               2 (==)
              9 POP_TOP
             10 LOAD_CONST               1 (None)
             13 RETURN_VALUE

यहाँ, जैसा कि आप देख रहे हैं, आप केवल उन दो (0, 0)टुपल्स की तुलना कर रहे हैं और वापस लौट रहे हैं True


20

समस्या को समझाने का एक और तरीका: आप शायद शब्दकोश शाब्दिक से परिचित हैं

{ "a": 1, "b": 2, "c": 3 }

और सरणी शाब्दिक

[ "a", "b", "c" ]

और टुपल शाब्दिक

( 1, 2, 3 )

लेकिन आपको जो एहसास नहीं होता है, वह यह है कि शब्दकोश और एरे के शाब्दिकों के विपरीत, आमतौर पर आप जो टुपल लिटरल देखते हैं , वह शाब्दिक वाक्य-विन्यास का हिस्सा नहीं होता है । टुपल्स के लिए शाब्दिक वाक्य-विन्यास केवल अल्पविराम द्वारा अलग किए गए भावों का एक क्रम है:

1, 2, 3

( पायथन के लिए औपचारिक व्याकरण की भाषा में एक "विस्तारक" )।

अब, आप सरणी शाब्दिक की क्या उम्मीद करते हैं

[ 0, 0 == (0, 0) ]

किसका मूल्यांकन करना है? वह शायद बहुत अधिक लग रहा है जैसे कि यह वैसा ही होना चाहिए

[ 0, (0 == (0, 0)) ]

कौन से पाठ्यक्रम का मूल्यांकन करता है [0, False]। इसी तरह, एक स्पष्ट रूप से छोटा टुपल शाब्दिक के साथ

( 0, 0 == (0, 0) )

यह आश्चर्य की बात नहीं है (0, False)। लेकिन कोष्ठक वैकल्पिक हैं;

0, 0 == (0, 0)

एक ही बात है। और इसीलिए आपको मिलता है (0, False)


यदि आप सोच रहे हैं कि टुपल शाब्दिक के चारों ओर कोष्ठक वैकल्पिक क्यों हैं, तो यह बड़े पैमाने पर है क्योंकि इस तरह से विनाशकारी असाइनमेंट लिखना कष्टप्रद होगा:

(a, b) = (c, d) # meh
a, b = c, d     # better

17

जिस क्रम में कार्रवाई की जाती है उसके आसपास कुछ कोष्ठकों को जोड़ने से आपको परिणाम बेहतर समझने में मदद मिल सकती है:

# Build two element tuple comprising of 
# (0, 0) == 0 result and 0
>>> ((0, 0) == 0), 0
(False, 0)

# Build two element tuple comprising of
# 0 and result of (0, 0) == 0 
>>> 0, (0 == (0, 0))
(0, False)

# Create two tuples with elements (0, 0) 
# and compare them
>>> (0, 0) == (0, 0) 
True

अल्पविराम का उपयोग अलग-अलग अभिव्यक्तियों के लिए किया जाता है (कोष्ठकों का उपयोग करके हम अलग-अलग व्यवहार को बाध्य कर सकते हैं, निश्चित रूप से)। आपके द्वारा सूचीबद्ध स्निपेट को देखने के दौरान, अल्पविराम ,इसे अलग कर देगा और परिभाषित करेगा कि किन भावों का मूल्यांकन किया जाएगा:

(0, 0) == 0 ,   0
#-----------|------
  expr 1      expr2

ट्यूपल (0, 0)को भी इसी तरह से तोड़ा जा सकता है। अल्पविराम शाब्दिक अर्थों से युक्त दो भावों को अलग करता है 0


6

पहले एक पायथन में दो चीजों का एक संयोजन बना रहा है:

  1. अभिव्यक्ति (0, 0) == 0, जिसका मूल्यांकन करता हैFalse
  2. अटल 0

दूसरे में यह चारों ओर दूसरा रास्ता है।


0

इस उदाहरण को देखें:

r = [1,0,1,0,1,1,0,0,0,1]
print(r==0,0,r,1,0)
print(r==r,0,1,0,1,0)

फिर परिणाम:

False 0 [1, 0, 1, 0, 1, 1, 0, 0, 0, 1] 1 0
True 0 1 0 1 0

तब तुलना उदाहरण में पहले नंबर (0 और r) से होती है।

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