2015-05-10 6 views
106

अजगर 3.4 में, मैंखाली सूची को असाइन नहीं किया जा रहा है (उदा। [] = "") एक त्रुटि?

[] = "" 

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

[] =() 

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

"" = [] 

() = "" 

जैसे कि उम्मीद एक अपवाद को जन्म देती है, जैसे कि उम्मीद एक अपवाद को जन्म देती है। तो क्या चल रहा है?

उत्तर

128

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

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

foo, bar = 1, 2 

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

जब आप ऐसा करेंगे:

[] = "" 

आप नामों में से एक खाली सूची के लिए एक खाली अनुक्रम (रिक्त स्ट्रिंग दृश्यों अभी भी) सौंपा। जहां foo = "a", bar = "b" और baz = "c", साथ लेकिन कम वर्ण के साथ समाप्त

[foo, bar, baz] = "abc" 

:

यह अनिवार्य कर के रूप में एक ही बात है।

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

देखें Assignment statements documentation:

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

और

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

जोर मेरा

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

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

भी देखें Why is it valid to assign to an empty list but not to an empty tuple?

34

यह दस्तावेज़ से Assignment statements section नियमों का पालन करती,

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

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

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

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

[] = "" 

"" एक 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 

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

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

यहाँ, के बाद से स्ट्रिंग खाली है की तरह है अनपेक्स 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 होगा और अंतिम होगा। फिर यह स्टैक के शीर्ष से बाएं हाथ की ओर से एक तरफ से चर के चर से असाइन करता है।


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

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

तुम भी उपयोग कर सकते हैं 'जिले ('[] =" "')' बुला बिना 'संकलन()'। –

+0

क्या आप वर्णन कर सकते हैं कि क्या होता है यदि आप अपने अंतिम उदाहरण में विधि का उपयोग करके तीन से अधिक चर/तत्वों को स्वैप कर रहे हैं? – hexafraction

+0

@hexafraction यह दायीं तरफ के सभी तत्वों के साथ एक नया ट्यूपल बनाएगा और फिर यह बाईं ओर चर के ऊपर उन्हें अनपैक करेगा। – thefourtheye

संबंधित मुद्दे