यह वहाँ प्रत्येक विधि के लिए "लाभ" कर रहे हैं कि क्या कहने के लिए नहीं बल्कि व्यक्तिपरक है।
हालांकि, हुड के नीचे जो भी हो रहा है, उसकी अच्छी समझ से यह प्रत्येक अवसर के लिए सबसे अच्छा विकल्प चुनने के लिए प्राकृतिक बना देगा।
एक सजावटी (फ़ंक्शन सजावट के बारे में बात करना), केवल एक कॉल करने योग्य ऑब्जेक्ट है जो एक इनपुट पैरामीटर के रूप में कार्य करता है। पायथन के पास इसके बजाय दिलचस्प डिजाइन है जो को अन्य प्रकार के कॉल करने योग्य ऑब्जेक्ट्स बनाने के लिए फ़ंक्शन के अलावा अनुमति देता है - और कोई भी अवसर पर अधिक रखरखाव या छोटा कोड बनाने के लिए का उपयोग करने के लिए रख सकता है।
डेकोरेटर के लिए
def a(x):
...
a = my_decorator(a)
कि इसके अलावा एक "वाक्यात्मक शॉर्टकट 'के रूप में अजगर 2.3 में वापस जोड़ा गया था, हम आम तौर सज्जाकार फोन कुछ" callables "है कि नहीं बल्कि" डेकोरेटर कारखानों "हो सकता है - जब हम इस तरह का उपयोग करें :
@my_decorator(param1, param2)
def my_func(...):
...
कॉल param1 और param2 के साथ "my_decorator" करने के लिए किया जाता है - यह तो एक उद्देश्य यह है कि फिर से बुलाया जाएगा, इस समय एक पैरामीटर के रूप "my_func" होने देता है। इसलिए, इस मामले में, तकनीकी रूप से "सजावट" जो भी "my_decorator" द्वारा लौटाया जाता है, इसे "सजावटी कारखाना" बना देता है।
अब, सजाए गए या सजावटी कारखानों को आमतौर पर कुछ आंतरिक स्थिति रखना है। पहले मामले में, केवल एक चीज जो रखती है वह मूल फ़ंक्शन का संदर्भ है (आपके उदाहरणों में f
नामक चर)। एक "सजावटी कारखाना" ऊपर दिए गए उदाहरण में अतिरिक्त राज्य चर ("param1" और "param2" पंजीकृत करना चाहता है)।
यह अतिरिक्त स्थिति, कार्यों के रूप में लिखे गए सजावटी के मामले में संलग्न कार्यों के भीतर चर में रखा जाता है, और वास्तविक रैपर फ़ंक्शन द्वारा "nonlocal" चर के रूप में उपयोग किया जाता है। यदि कोई उचित वर्ग लिखता है, तो उन्हें सजावटी फ़ंक्शन में उदाहरण चर के रूप में रखा जा सकता है (जिसे "कॉल करने योग्य ऑब्जेक्ट" के रूप में देखा जाएगा, न कि "फ़ंक्शन") - और उन तक पहुंच अधिक स्पष्ट और अधिक पठनीय है।
तो, ज्यादातर मामलों में यह पठनीयता की बात है कि आप एक दृष्टिकोण या दूसरे को पसंद करेंगे: छोटे, सरल सजावटी के लिए, कार्यात्मक दृष्टिकोण अक्सर कक्षा के रूप में लिखे गए एक से अधिक पठनीय होता है - जबकि कभी-कभी एक और विस्तृत एक - विशेष रूप से एक "सजावटी कारखाना" "पाइथन कोडिंग" के बारे में सलाह "फ्लैट नेस्टेड से बेहतर है" का पूरा फायदा उठाएगा।
पर विचार करें:
class MyDecorator(object):
"""Decorator example mixing class and function definitions."""
def __init__(self, func, param1, param2):
self.func = func
self.param1, self.param2 = param1, param2
def __call__(self, *args, **kwargs):
...
#use self.param1
result = self.func(*args, **kwargs)
#use self.param2
return result
def my_dec_factory(param1, param2):
def decorator(func):
return MyDecorator(func, param1, param2)
return decorator
अद्यतन:
def my_dec_factory(param1, param2):
...
...
def real_decorator(func):
...
def wraper_func(*args, **kwargs):
...
#use param1
result = func(*args, **kwargs)
#use param2
return result
return wraper_func
return real_decorator
इस "संकर" समाधान के खिलाफ
मिसिंग यू "शुद्ध वर्ग" सज्जाकार
अब के रूपों, ध्यान दें "संकर" विधि सबसे छोटी और अधिक पठनीय कोड रखने की कोशिश कर रहे "दोनों दुनिया के सर्वश्रेष्ठ" लेती है। एक पूर्ण "डेकोरेटर कारखाने" वर्गों के साथ विशेष रूप से परिभाषित या तो पता करने के लिए दो वर्गों, या एक "मोड" विशेषता की आवश्यकता होगी अगर यह सजाया समारोह रजिस्टर करने के लिए बुलाया गया था या वास्तव में अंतिम समारोह कॉल करने के लिए:
class MyDecorator(object):
"""Decorator example defined entirely as class."""
def __init__(self, p1, p2):
self.p1 = p1
...
self.mode = "decorating"
def __call__(self, *args, **kw):
if self.mode == "decorating":
self.func = args[0]
self.mode = "calling"
return self
# code to run prior to function call
result = self.func(*args, **kw)
# code to run after function call
return result
@MyDecorator(p1, ...)
def myfunc():
...
और अंत में एक शुद्ध, "सफेद colar" डेकोरेटर दो वर्गों के साथ परिभाषित - हो सकता है और अधिक अलग बातें रखते हुए, लेकिन एक बात करने के लिए अतिरेक में वृद्धि एक नहीं कह सकता कि यह अधिक पोषणीय है:
class Stage2Decorator(object):
def __init__(self, func, p1, p2, ...):
self.func = func
self.p1 = p1
...
def __call__(self, *args, **kw):
# code to run prior to function call
...
result = self.func(*args, **kw)
# code to run after function call
...
return result
class Stage1Decorator(object):
"""Decorator example defined as two classes.
No "hacks" on the object model, most bureacratic.
"""
def __init__(self, p1, p2):
self.p1 = p1
...
self.mode = "decorating"
def __call__(self, func):
return Stage2Decorator(func, self.p1, self.p2, ...)
@Stage1Decorator(p1, p2, ...)
def myfunc():
...
एक महत्वपूर्ण बात: अपने वास्तविक आवरण कार्यों मूल 'f' फ़ंक्शन को कॉल लेकिन कॉल प्राप्त करने वाला के लिए अपने दिए गए मान नहीं लौटते: इस सबसे अधिक संभावना एक गलत व्यवहार करने के लिए नेतृत्व करेंगे। – jsbueno
संभावित डुप्लिकेट [सजावटी वर्गों और सजावटी कार्यों के बीच अंतर] (http://stackoverflow.com/questions/4650333/difference-between-decorator-classes-and-decorator- क्रियाएं) –