2010-08-19 9 views
6

निम्नलिखित कोड को देखते हुए हल करने:अजगर चर

a = 0 
def foo(): 
    # global a 
    a += 1 
foo() 

जब चलाने के लिए, अजगर की शिकायत: UnboundLocalError: स्थानीय चर 'एक' असाइनमेंट से पहले संदर्भित

हालांकि, जब यह एक शब्दकोश है ...

a = {} 
def foo(): 
    a['bar'] = 0 
foo() 

यह बात ठीक है ...

कोई भी जानता है कि हम संदर्भ क्यों दे सकते हैं कोड के दूसरे हिस्से में, लेकिन पहले नहीं?

उत्तर

2

अंतर यह है कि पहले उदाहरण में आप a जो एक नया स्थानीय नाम a कि वैश्विक a खाल पैदा करने के लिए बताए जाते हैं।

दूसरे उदाहरण में आप a पर असाइनमेंट नहीं कर रहे हैं इसलिए वैश्विक a का उपयोग किया जाता है।

यह documentation में शामिल है।

A special quirk of Python is that – if no global statement is in effect – assignments to names always go into the innermost scope.

+0

मुझे आश्चर्य है कि उन्होंने इसे 'विशेष क्विर्क' के रूप में वर्णित करने का फैसला क्यों किया? जावास्क्रिप्ट के साथ तुलना करें जहां 'a = 1' स्वचालित रूप से वैश्विक दायरे को असाइन करता है! इसके बारे में एकमात्र अच्छी बात यह है कि आप 'var a = 1' की अनुपस्थिति से कचरा कोड को तुरंत पहचान सकते हैं – aaronasterling

1

प्रश्न अद्यतन में से एक है।

आप a अपडेट नहीं कर सकते क्योंकि यह आपके फ़ंक्शन के स्थानीय नामस्थान में एक चर नहीं है। अपडेट-इन-प्लेस असाइनमेंट ऑपरेशन a को स्थान पर अपडेट करने में विफल रहता है।

दिलचस्प बात यह है कि a = a + 1 भी विफल रहता है।

पायथन इस तरह के बयान के लिए थोड़ा अनुकूलित कोड उत्पन्न करता है। यह एक "LOAD_FAST" निर्देश का उपयोग करता है।

2   0 LOAD_FAST    0 (a) 
       3 LOAD_CONST    1 (1) 
       6 INPLACE_ADD   
       7 STORE_FAST    0 (a) 
      10 LOAD_CONST    0 (None) 
      13 RETURN_VALUE   

ध्यान दें कि बराबर के चिह्न के बाईं और दाईं ओर a के उपयोग के इस अनुकूलन की ओर जाता है।

हालांकि, आप a तक पहुंच सकते हैं क्योंकि पायथन आपके लिए स्थानीय और वैश्विक नामस्थान खोजेगा।

चूंकि a असाइनमेंट स्टेटमेंट के बाईं ओर दिखाई नहीं देता है, तो एक अलग प्रकार की पहुंच का उपयोग किया जाता है, "LOAD_GLOBAL"।

2   0 LOAD_CONST    1 (0) 
       3 LOAD_GLOBAL    0 (a) 
       6 LOAD_CONST    2 ('bar') 
       9 STORE_SUBSCR   
      10 LOAD_CONST    0 (None) 
      13 RETURN_VALUE   
0

a += 1a = a + 1 के बराबर है। परिवर्तनीय a को असाइन करके, इसे स्थानीय बनाया जाता है। a + 1 असाइन करने का प्रयास करने वाला मान विफल रहता है क्योंकि a अभी तक बाध्य नहीं है।

0

एक बहुत आम अजगर पकड़ लिया है कि: यदि आप एक समारोह के अंदर एक चर करने के लिए (के रूप में आप कर += साथ,) सब पर (जरूरी नहीं इससे पहले कि आप किसी अन्य तरीके का उपयोग करें) असाइन करते हैं, कहीं भी, यह नहीं है वैश्विक एक का उपयोग करें। हालांकि, चूंकि आप जो कर रहे हैं वह प्रभावी रूप से "ए = ए + 1" है, आप इसे निर्दिष्ट करने से पहले a (अभिव्यक्ति के दाईं ओर) तक पहुंचने का प्रयास कर रहे हैं।

अपने फ़ंक्शन की शुरुआत में global a का उपयोग करने का प्रयास करें (लेकिन सावधान रहें कि आप वैश्विक a मान को ओवरराइट कर देंगे)।

अपने दूसरे उदाहरण पर, आप परिवर्तनीय a निर्दिष्ट नहीं कर रहे हैं, लेकिन केवल इसकी एक आइटम में से एक है। तो वैश्विक निर्देश a का उपयोग किया जाता है।