2012-08-29 14 views
8

खोने वाले पायथन क्लोजर फ़ंक्शन मैंने अभी पाइथन @ सजावट सीखा है, यह अच्छा है, लेकिन जल्द ही मैंने पाया कि मेरा संशोधित कोड अजीब समस्याएं आ रहा है।बाहरी परिवर्तनीय पहुंच

def with_wrapper(param1): 
    def dummy_wrapper(fn): 
     print param1 
     param1 = 'new' 
     fn(param1) 
    return dummy_wrapper 

def dummy(): 
    @with_wrapper('param1') 
    def implementation(param2): 
     print param2 

dummy() 

मैं इसे डिबग, यह प्रिंट param1

UnboundLocalError: local variable 'param1' referenced before assignment 

पर अपवाद बाहर फेंक अगर मैं param1 = 'new' इस लाइन, इस दिनचर्या निकालने के लिए, किसी भी संशोधित आपरेशन के बिना बाहरी गुंजाइश से चर (नई वस्तु के लिए लिंक) काम कर सकता है

क्या इसका अर्थ है कि मैंने केवल बाहरी स्कोप चर के एक प्रति बनाये हैं, फिर संशोधन करें?


धन्यवाद डेलनान, इसे बंद करना आवश्यक है। यहाँ से संभावना जवाब: What limitations have closures in Python compared to language X closures?

इसी कोड के रूप में:

def e(a): 
    def f(): 
     print a 
     a = '1' 
    f() 
e('2') 

और यह भी इस पिछले कष्टप्रद वैश्विक चर लगता है:

a = '1' 
def b(): 
    #global a 
    print a 
    a = '2' 
b() 

यह द्वारा वैश्विक प्रतीक जोड़ना तय हो गई है। लेकिन बंद करने के लिए, ऐसा कोई प्रतीक नहीं मिला। धन्यवाद unutbu, पायथन 3 हमें nonlocal दिया।

मुझे ऊपर से सीधे बाहरी चर तक पहुंचने से पता है केवल पढ़ने के लिए है। लेकिन यह पहले पढ़ने वाले चर (प्रिंट var) को देखने के लिए असहज है, यह भी प्रभावित है।

+0

की [संभव डुप्लिकेट क्या सीमाएं भाषा एक्स बंद होने की तुलना में पाइथन में बंद हो गया है?] (http://stackoverflow.com/questions/141642/what-limitations-have-closures-in-python-compared-to-language-x-closures) – delnan

+0

यह बिल्कुल है सजावटी बीटीडब्ल्यू के साथ कुछ नहीं करना। – delnan

+0

हां, यह बंद होने में होता है। इस तरह: डीईएफ़ ई (क): डीईएफ़ च(): प्रिंट एक एक = '1' च() ई ('123') –

उत्तर

11

अजगर एक समारोह को पार्स करता है, यह नोट जब भी यह एक चर एक काम के बाएं हाथ की ओर पर इस्तेमाल किया, जैसे

param1 = 'new' 

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

print param1 

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


python3 में आप घोषणा की कि param1 nonlocal है करके इसे ठीक कर सकते हैं:

def with_wrapper(param1): 
    def dummy_wrapper(fn): 
     nonlocal param1 
     print param1 
     param1 = 'new' 
     fn(param1) 
    return dummy_wrapper 

को Python2 में आप इस तरह के एक सूची के अंदर param1 गुजर के रूप में एक चाल का सहारा लेना, है (या कुछ अन्य परिवर्तनशील वस्तु):

def with_wrapper(param1_list): 
    def dummy_wrapper(fn): 
     print param1_list[0] 
     param1_list[0] = 'new' # mutate the value inside the list 
     fn(param1_list[0]) 
    return dummy_wrapper 

def dummy(): 
    @with_wrapper(['param1']) # <--- Note we pass a list here 
    def implementation(param2): 
     print param2 
+0

काम करती हैं और इसे 'ठीक करने' का अच्छा तरीका क्या है? – Silox

+1

... असाइनमेंट के बाद 'प्रिंट' कथन डालें? – kindall

+0

व्याख्या करने के लिए धन्यवाद। लेकिन मुझे इस बारे में कोई जानकारी नहीं है कि क्यों param1 = 'new' बाहरी परम को फिर से सौंपता है लेकिन एक स्थानीय var बनाने के लिए। –

0

आप समारोह है, जो ०१२३४५३८६९ बनाता में param1 आवंटितएक स्थानीय चर। हालांकि, इसे उस बिंदु पर असाइन नहीं किया गया है जिसे आप प्रिंट कर रहे हैं, इसलिए आपको एक त्रुटि मिलती है। पाइथन बाहरी क्षेत्रों में चर की तलाश में वापस नहीं आते हैं।

+0

_print param1_ एक उदाहरण है, वास्तविक कोड में, param1 पर कोई संदर्भ प्रतिबंधित है जब param1 = xx मौजूद है –

1

यदि आप पाइथन 2.x में बाहरी दायरे से एक चर को कैप्चर करना चाहते हैं तो ग्लोबल का उपयोग करना भी एक विकल्प है (सामान्य प्रावधानों के साथ - लेकिन अस्थायी परिस्थितियों या अन्वेषण कोड के लिए आसान)।

निम्नलिखित फेंक करते हैं (भीतरी भीतर outer1 का काम यह स्थानीय और इसलिए अगर हालत में असीम बनाता है):

def outer(): 
    outer1 = 1 
    def inner(): 
     if outer1 == 1: 
      outer1 = 2 
      print('attempted to accessed outer %d' % outer1) 

यह कार्य नहीं करेंगे:

def outer(): 
    global outer1 
    outer1 = 1 
    def inner(): 
     global outer1 
     if outer1 == 1: 
      outer1 = 2 
      print('accessed outer %d' % outer1) 
संबंधित मुद्दे