एक खाली सूची (जैसे [] = "") को कोई त्रुटि क्यों नहीं बता रहा है?


110

अजगर 3.4 में, मैं टाइप कर रहा हूं

[] = "" 

और यह ठीक काम करता है, कोई अपवाद नहीं उठाया जाता है। हालांकि बाद के []बराबर नहीं है ""

[] = ()

यह भी ठीक काम करता है।

"" = []

उम्मीद के मुताबिक एक अपवाद बढ़ा,

() = ""

हालांकि उम्मीद के मुताबिक एक अपवाद बढ़ा है। तो क्या हो रहा है?

जवाबों:


132

आप समानता के लिए तुलना नहीं कर रहे हैं। आप असाइन कर रहे हैं ।

अजगर आपको कई लक्ष्यों को सौंपने की अनुमति देता है:

foo, bar = 1, 2

क्रमशः fooऔर bar, दो मान प्रदान करता है। आपको बस एक है अनुक्रम या iterable दाएँ हाथ की ओर पर, और बाईं तरफ के नामों की सूची या टपल।

जब तुम करोगे:

[] = ""

आपने नामों की एक खाली सूची में एक खाली अनुक्रम (खाली तार अभी भी अनुक्रम हैं) सौंपा ।

यह अनिवार्य रूप से ऐसा ही है:

[foo, bar, baz] = "abc"

जहाँ आप के साथ अंत है foo = "a", bar = "b"और baz = "c", लेकिन कम पात्रों के साथ।

हालाँकि, आप एक स्ट्रिंग को असाइन नहीं कर सकते हैं, इसलिए ""असाइनमेंट के बाईं ओर कभी भी काम नहीं करता है और हमेशा सिंटैक्स त्रुटि होती है।

असाइनमेंट स्टेटमेंट प्रलेखन देखें :

एक असाइनमेंट स्टेटमेंट अभिव्यक्ति की सूची का मूल्यांकन करता है (याद रखें कि यह एकल अभिव्यक्ति या अल्पविराम से अलग की गई सूची हो सकती है, बाद में एक ट्यूपल की पैदावार) और लक्ष्य सूची में से प्रत्येक के लिए एकल परिणामी वस्तु को बाईं से दाईं ओर असाइन करता है।

तथा

ऑब्जेक्ट को लक्ष्य सूची में संरेखित करना , वैकल्पिक रूप से कोष्ठक या वर्ग कोष्ठक में संलग्न , पुनरावर्ती रूप से निम्नानुसार परिभाषित किया गया है।

जोर मेरा

वह पायथन खाली सूची के लिए एक वाक्यविन्यास त्रुटि नहीं फेंकता है, वास्तव में एक बग है! आधिकारिक रूप से प्रलेखित व्याकरण एक खाली लक्ष्य सूची के लिए अनुमति नहीं देता है, और खाली के लिए ()आपको एक त्रुटि मिलती है। बग 23275 देखें ; इसे हानिरहित बग माना जाता है:

शुरुआती बिंदु यह पहचान रहा है कि यह बहुत लंबे समय से आसपास है और हानिरहित है।

यह भी देखें कि खाली सूची पर असाइन करना क्यों मान्य है लेकिन खाली ट्यूपल के लिए नहीं?


36

यह प्रलेखन से असाइनमेंट स्टेटमेंट सेक्शन के नियमों का पालन करता है,

assignment_stmt ::=  (target_list "=")+ (expression_list | yield_expression)

यदि target listलक्ष्य की अल्पविराम से अलग की गई सूची है: वस्तु को उतने ही आइटम के साथ एक पुनरावृत्त होना चाहिए जितना कि लक्ष्य सूची में लक्ष्य होते हैं, और आइटम को असाइन किया जाता है, बाएं से दाएं, इसी लक्ष्य तक।

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

इसलिए, जब आप कहें

[] = ""

"" एक iterable है (किसी भी मान्य अजगर स्ट्रिंग एक iterable है) और यह सूची के तत्वों पर अनपैक किया जा रहा है।

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

>>> [a, b, c] = "123"
>>> a, b, c
('1', '2', '3')

चूंकि आपके पास एक खाली स्ट्रिंग, और एक खाली सूची है, इसलिए अनपैक करने के लिए कुछ भी नहीं है। तो, कोई त्रुटि नहीं।

लेकिन, यह कोशिश करो

>>> [] = "1"
Traceback (most recent call last):
  File "<input>", line 1, in <module>
ValueError: too many values to unpack (expected 0)
>>> [a] = ""
Traceback (most recent call last):
  File "<input>", line 1, in <module>
ValueError: need more than 0 values to unpack

में [] = "1"मामला है, आप स्ट्रिंग खोल की कोशिश कर रहे "1"चर के एक खाली सूची के ऊपर। तो यह "बहुत सारे मूल्यों को अनपैक करने के लिए (अपेक्षित 0)" के साथ शिकायत करता है।

उसी तरह, [a] = ""यदि आपके पास एक खाली स्ट्रिंग है, तो वास्तव में अनपैक करने के लिए कुछ भी नहीं है, लेकिन आप इसे एक चर पर अनपैक कर रहे हैं, जो कि फिर से संभव नहीं है। यही कारण है कि यह शिकायत करता है "अनपैक करने के लिए 0 से अधिक मूल्यों की आवश्यकता है"।

इसके अलावा, जैसा कि आपने देखा,

>>> [] = ()

यह भी कोई त्रुटि नहीं है, क्योंकि ()एक खाली टपल है।

>>> ()
()
>>> type(())
<class 'tuple'>

और जब यह एक खाली सूची में अनपैक किया जाता है, तो अनपैक करने के लिए कुछ भी नहीं होता है। तो कोई त्रुटि नहीं।


लेकिन, जब आप करते हैं

>>> "" = []
  File "<input>", line 1
SyntaxError: can't assign to literal
>>> "" = ()
  File "<input>", line 1
SyntaxError: can't assign to literal

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

>>> 1 = "one"
  File "<input>", line 1
SyntaxError: can't assign to literal

internals

आंतरिक रूप से, इस असाइनमेंट ऑपरेशन का अनुवाद UNPACK_SEQUENCEऑप कोड में किया जाएगा,

>>> dis(compile('[] = ""', "string", "exec"))
  1           0 LOAD_CONST               0 ('')
              3 UNPACK_SEQUENCE          0
              6 LOAD_CONST               1 (None)

यहां, चूंकि स्ट्रिंग खाली है, बार बार UNPACK_SEQUENCEअनपैक करता 0है। लेकिन जब आपके पास ऐसा कुछ हो

>>> dis(compile('[a, b, c] = "123"', "string", "exec"))
  1           0 LOAD_CONST               0 ('123')
              3 UNPACK_SEQUENCE          3
              6 STORE_NAME               0 (a)
              9 STORE_NAME               1 (b)
             12 STORE_NAME               2 (c)
             15 LOAD_CONST               1 (None)
             18 RETURN_VALUE

अनुक्रम 123को स्टैक में अनपैक किया गया है, दाएं से बाएं। तो, स्टैक का शीर्ष होगा 1और अगला होगा 2और अंतिम होगा 3। फिर यह स्टैक के ऊपर से लेफ्ट हैंड साइड एक्सप्रेशन से एक-एक करके वैरिएबल को असाइन करता है।


BTW, पायथन में, यह है कि आप एक ही अभिव्यक्ति में कई असाइनमेंट कैसे कर सकते हैं। उदाहरण के लिए,

a, b, c, d, e, f = u, v, w, x, y, z

यह काम करता है क्योंकि, एक टुपल के निर्माण के लिए दाहिने हाथ के मूल्यों का उपयोग किया जाता है और फिर इसे बाएं हाथ की ओर के मूल्यों पर अनपैक किया जाएगा।

>>> dis(compile('a, b, c, d, e, f = u, v, w, x, y, z', "string", "exec"))
  1           0 LOAD_NAME                0 (u)
              3 LOAD_NAME                1 (v)
              6 LOAD_NAME                2 (w)
              9 LOAD_NAME                3 (x)
             12 LOAD_NAME                4 (y)
             15 LOAD_NAME                5 (z)
             18 BUILD_TUPLE              6
             21 UNPACK_SEQUENCE          6
             24 STORE_NAME               6 (a)
             27 STORE_NAME               7 (b)
             30 STORE_NAME               8 (c)
             33 STORE_NAME               9 (d)
             36 STORE_NAME              10 (e)
             39 STORE_NAME              11 (f)
             42 LOAD_CONST               0 (None)
             45 RETURN_VALUE

लेकिन क्लासिक स्वैपिंग तकनीक a, b = b, aस्टैक के शीर्ष में तत्वों के रोटेशन का उपयोग करती है। यदि आपके पास केवल दो या तीन तत्व हैं, तो उन्हें ट्यूल और अनपैकिंग के निर्माण के बजाय विशेष ROT_TWOऔर ROT_THREEनिर्देशों के साथ व्यवहार किया जाता है ।

>>> dis(compile('a, b = b, a', "string", "exec"))
  1           0 LOAD_NAME                0 (b)
              3 LOAD_NAME                1 (a)
              6 ROT_TWO
              7 STORE_NAME               1 (a)
             10 STORE_NAME               0 (b)
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE

आप dis('[] = ""')बिना कॉल किए भी उपयोग कर सकते हैं compile()
एंड्रिया कोरबेलिनी

क्या आप बता सकते हैं कि यदि आप अपने अंतिम उदाहरण में विधि का उपयोग करके तीन से अधिक चर / तत्वों की अदला-बदली कर रहे हैं, तो क्या होगा?
नानोफारड

@ हेक्सफ़्रेक्शन यह दाहिने हाथ की तरफ के सभी तत्वों के साथ एक नया ट्यूपल बनाएगा और फिर इसे बाएं हाथ की तरफ वाले वेरिएबल पर अनपैक करेगा।
Thefourtheye

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