2012-09-15 14 views
6

मैं समझने की कोशिश कर रहा हूं कि सजावटी कैसे काम करते हैं, और यह सोच रहा था कि सजाए गए फ़ंक्शन सजावटी के चर का उपयोग कर सकते हैं या नहीं। उदाहरण के लिए, निम्नलिखित कोड में, मैं f1 को स्थानीय वैरिएबल तक कैसे पहुंच सकता हूं? क्या यह संभव है, और क्या यह चीजों को करने का भी एक अच्छा तरीका है?सजावट के सजावटी फ़ंक्शन एक्सेस वैरिएबल

def funcDec(func): 
    localVariable = "I'm a local string" 
    def func2Return(*args):                    
     print "Calling localVariable from decorator " + localVariable 
     func(*args)          
     print "done with calling f1" 
    return func2Return 

@funcDec 
def f1(x, y): 
    print x + y 
    print localVariable 

f1(2, 3) 

उत्तर

4

नहीं, आप नहीं कर सकते। this previous question देखें। सिर्फ इसलिए कि फ़ंक्शन एक सजावट वाला नहीं है, इसका मतलब यह नहीं है कि इसे कॉल करने के लिए इसके चर के लिए विशेष पहुंच होती है। आप ऐसा करते हैं:

def func(): 
    a = 2 
    otherFunc() 

फिर otherFunc चर a के लिए उपयोग नहीं है। इस तरह यह सभी फ़ंक्शन कॉल के लिए काम करता है, और यह सजावटी के लिए भी काम करता है।

अब, आवरण समारोह आप (अपने उदाहरण में func2Return) डेकोरेटर के अंदर परिभाषित करता है कि समारोह उन चर के रूप में एक ही दायरे में lexically है क्योंकि, चर की पहुंच है। तो आपकी लाइन print "Calling localVariable from decorator " + localVariable काम करेगी। सजावट वाले व्यवहार को व्यवहार के साथ लपेटने के लिए आप इसे कुछ हद तक उपयोग कर सकते हैं जो सजावटी में चर पर निर्भर करता है। लेकिन वास्तव में समारोह को सजाया जा रहा है (f1 आपके उदाहरण में) उन चरों तक पहुंच नहीं है।

एक फ़ंक्शन के पास केवल उस क्षेत्र से स्थानीय चर तक पहुंच है जहां फ़ंक्शन परिभाषा वास्तव में है। कार्य स्कोप कॉल करने से चर नहीं मिलता है। (यह एक अच्छी बात है। अगर वे किया था, यह एक बड़ी गड़बड़ हो जाएगा।)

+0

भी देखें: http://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scoping_and_dynamic_scoping – georg

5

मैं इसे मदद करता है अगर आप एक डेकोरेटर ध्यान रखें कि लगता है

@deco 
def f(...): ... 

के लिए बस वाक्यात्मक चीनी है
def f(...): ... 
f = deco(f) 

किसी प्रकार के मैक्रो विस्तार के बजाय। पायथन में एक चर के दायरे को स्थिर रूप से निर्धारित किया जाता है, इसलिए वैश्विक (मॉड्यूल-स्तर) एक चर के लिए काम करता है जिसे न तो एक तर्क के रूप में पारित किया जाता है और न ही असाइन किया गया है, जिसे वैश्विक नामस्थान में देखा जाएगा।

इसलिए आपको func2Return() स्पष्ट रूप से स्थानीय चर पर जाना होगा। f1(x, y, localvariable=None) को f1 के हस्ताक्षर बदलें और

f1(*args, localvariable=localvariable) 
7
क्योंकि पायथन के scoping नियमों का

साथ आवरण समारोह fun2Return इसे कहते है, एक सजाया समारोह आम तौर पर डेकोरेटर में किसी भी चर का उपयोग नहीं कर सकते हैं।

def funcDec(func): 
    localVariable = "I'm a local string" 

    def wrapped(*args): 
     print("Calling localVariable from funcDec " + localVariable) 
     func(*args) 
     print("done with calling f1") 

    wrapped.attrib = localVariable 
    return wrapped 

@funcDec 
def f1(x, y): 
    print(x + y) 
    print('f1.attrib: {!r}'.format(f1.attrib)) 

f1(2, 3) 

निम्नलिखित में से कौन उत्पादन का उत्पादन होगा::

Calling localVariable from decorator I'm a local string 
5 
f1.attrib: "I'm a local string" 
done with calling f1 
हालांकि, बाद से कार्यों उन्हें सौंपे गए मनमाने ढंग से गुण हो सकता है, आप डेकोरेटर के बाद ऐसा ही प्रभाव प्राप्त करने के लिए की तरह कुछ कर सकता है

किसी ने पूछा कि क्या इसे कक्षा के तरीकों पर लागू किया जा सकता है: उत्तर "हां" है, लेकिन आपको विधि को संदर्भित करना है कक्षा स्वयं या इसके उदाहरण को self के रूप में पारित किया गया है तर्क। दोनों तकनीकें नीचे दिखाए गए हैं। self का उपयोग करना बेहतर है क्योंकि यह उस वर्ग के नाम से स्वतंत्र कोड बनाता है जिसमें यह है।

class Test(object): 
    @funcDec 
    def f1(self): 
     print('{}.f1() called'.format(self.__class__.__name__)) 
     print('self.f1.attrib: {!r}'.format(self.f1.attrib)) # Preferred. 
     print('Test.f1.attrib: {!r}'.format(Test.f1.attrib)) # Also works. 

print() 
test = Test() 
test.f1() 

आउटपुट:

Calling localVariable from funcDec I'm a local string 
Test.f1() called 
self.f1.attrib: "I'm a local string" 
Test.f1.attrib: "I'm a local string" 
done with calling f1 
+0

महान उदाहरण! क्या कक्षा में एक विधि के साथ किया जा सकता है? –

+0

@ केरथाना प्रभाकरन: हां, सजावटी कक्षा के तरीकों पर काम करेगा, लेकिन उन्हें अतिरिक्त विशेषता को अलग-अलग संदर्भित करने की आवश्यकता होगी: यानी 'self.method_name.attrib' जैसी कुछ। – martineau

+0

हाँ मैंने कोशिश की! लेकिन एक अपवाद मिला कि 'examplemethod' ऑब्जेक्ट में कोई विशेषता नहीं है 'attrib' –

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