2013-10-21 27 views
8

मैं अजगर सज्जाकार समझने की कोशिश कर रहा था और मैं करने के लिए एक बराबर प्रोग्राम लिखने के लिए कोशिश कर रहा था में __call__ इस एक:अजगर डेकोरेटर - वर्ग

class myDecorator(object): 
    def __init__(self, f): 
     print ("inside myDecorator.__init__()") 
     f() # Prove that function definition has completed 

    def __call__(self): 
     print ("inside myDecorator.__call__()") 

@myDecorator 
def aFunction(): 
    print ("inside aFunction()") 

print ("Finished decorating aFunction()") 

aFunction() 

समस्या मैं समझ नहीं कर रहा हूँ कैसे वर्ग के __call__ तरीका है अंत में aFunction() पर कॉल करके बुलाया जा रहा है।

aFunction()myDecorator.__call__(aFunction) द्वारा प्रतिस्थापित किया जा रहा है। क्या आप कृपया मेरी मदद कर सकते हैं? सजावट के बिना समकक्ष कार्यक्रम कैसे होगा?

धन्यवाद!

उत्तर

8

अपने कोड के उत्पादन में

inside myDecorator.__init__() 
inside aFunction() 
Finished decorating aFunction() 
inside myDecorator.__call__() 

सबसे पहले है, क्या तुम जानते हो, इस @ डेकोरेटर वाक्य रचना क्या मतलब है:

1

afunction को कक्षा myDecorator के उदाहरण के द्वारा प्रतिस्थापित किया जा रहा है। कक्षा में __call__ विधि है, इसलिए उदाहरण को फ़ंक्शन की तरह कहा जा सकता है। इस प्रकार, यह मानते हुए कि यह हस्ताक्षर संगत है (आमतौर पर एक सजावटी ऐसा कुछ देता है जो *args और **kwargs का उपयोग करता है), उदाहरण मूल फ़ंक्शन के प्रतिस्थापन के रूप में उपयोग किया जा सकता है।

आम तौर पर __call__ विधि लपेटा हुआ फ़ंक्शन कॉल करेगा। इसे __init__ में करना आम तौर पर गलत है; __init__ को लिपटे फ़ंक्शन के संदर्भ को एक उदाहरण विशेषता के रूप में संग्रहीत करना चाहिए, ताकि __call__ इसे कॉल कर सके।

1

यह एक सजावट का पूरा उद्देश्य है: सजावट द्वारा लौटाए गए फ़ंक्शन के साथ एक फ़ंक्शन को प्रतिस्थापित करने के लिए (या अधिक सामान्यतः लपेटें)। आपके मामले में, aFunction को myDecorator के उदाहरण के साथ प्रतिस्थापित किया जा रहा है, इसलिए जब आप aFunction() पर कॉल करते हैं तो आप वास्तव में उस उदाहरण को कॉल कर रहे हैं: और पायथन में, क्लास इंस्टेंस को कॉल करने से इसकी __call__ विधि आती है।

एक सजाया समारोह को परिभाषित करना वास्तव में इस के बराबर है:

def aFunction(): 
    print("inside aFunction()") 
aFunction = myDecorator(aFunction) 

आमतौर पर, जाहिर है, रैपिंग समारोह मूल कार्य कर रही है जो कुछ भी यह होता है के बाद कहेंगे।

class myDecorator(object): 
    def __init__(self, f): 
     print ("inside myDecorator.__init__()") 
     self.f = f #Store the function being wrapped 

    def __call__(self): 
     print ("inside myDecorator.__call__()") 
     self.f() # Call the wrapped function 
1

यहाँ एक ठीक है? आप मूल रूप से एक नया बनाने

def function(a): 
    pass 
function = decorator(function) 

तो, आपका मामले में

@myDecorator 
def aFunction(): 
    print ("inside aFunction()") 

अर्थ केवल यह है

def aFunction(): 
    print ("inside aFunction()") 
aFunction = myDecorator(aFunction) 

सबसे पहले,:

@decorator 
def function(a): 
    pass 

सिर्फ कहने का एक और तरीका है myDecorator वर्ग का उदाहरण, invoking यह कन्स्ट्रक्टर (__init__) है और इसे एक फ़ंक्शन फ़ंक्शन ऑब्जेक्ट पास कर रहा है। फिर, यह प्रिंट और दिए गए फ़ंक्शन निष्पादित करता है।साथ ही, ध्यान दें कि यह तब हो रहा है जब फ़ंक्शन को दुभाषिया द्वारा लोड किया जाता है, जब इसे निष्पादित नहीं किया जाता है, इसलिए यदि आप इस फ़ाइल से कुछ आयात करते हैं, तो यह निष्पादित होगा, उपयोग या कॉल पर नहीं।

फिर, aFunction() निष्पादित करते समय, जब एक फ़ंक्शन अभी भी मेरे डिकोरेटर उदाहरण को प्रतिबिंबित कर रहा है, तो यह मेरे डीकोरोरेटर की __call__ विधि को कॉल करने के लिए बनाता है, जो निष्पादित करता है। नोट, f() का अर्थ इस मामले में f.__call__(f) जैसा है, __call__ विधि का उपयोग डिफ़ॉल्ट ऑब्जेक्ट के कॉलिंग व्यवहार को सक्षम और ओवरराइड करने के लिए किया जाता है (सरलीकरण में, किसी ऑब्जेक्ट को कॉल करने योग्य होता है जब __call__ विधि परिभाषित होती है)।

यदि आप इसे कॉल करते समय एक निष्पादन निष्पादित करना चाहते हैं, तो आपको इसे __init__ में आवृत्ति चर निर्दिष्ट करना चाहिए और इसे मेरे डेकोरेटर के __call__ में आमंत्रित करना चाहिए।

+0

फ़ंक्शन के तर्कों को स्वीकार करने के लिए def __call __ (self, * args, ** kwargs) का उपयोग करें: और उन्हें f – theannouncer

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