के रूप में अन्य उत्तर समझा दिया है, सज्जाकार सामान्य रूप से एक भी निहित समारोह तर्क जब सिर्फ इस तरह उनके नाम का उपयोग करके लागू पारित कर रहे हैं:
@deco
def somefunc(...): pass
कौन सा रूप में एक ही बात करता है:
def somefunc(...): pass
somefunc = deco(somefunc)
इस स्थिति में तर्क फ़ंक्शन परिभाषा का एक संकलित संस्करण है जो तुरंत अनुसरण करता है। ऐसे मामलों में सजावटी एक कॉल करने योग्य लौटाता है जिसे संकलित फ़ंक्शन बॉडी के बजाय फ़ंक्शन नाम पर असाइन किया जाता है, जैसा आमतौर पर मामला होता है।
लेकिन अगर एक डेकोरेटर समारोह स्पष्ट रूप से एक या अधिक तर्क दिया जाता है जब यह इस तरह, लागू है:
@deco(args)
def somefunc(...): pass
यह के बराबर हो जाता है:
def somefunc(...): pass
somefunc = deco(args)(somefunc)
आप देख सकते हैं इस में बातें मामले कुछ अलग तरीके से काम करते हैं। सजावटी फ़ंक्शन अभी भी एक कॉल करने योग्य लौटाता है, केवल इस बार कि "सामान्य" एकल अंतर्निहित-तर्क सजावट फ़ंक्शन की अपेक्षा की जाती है, जिसे बाद में निम्न फ़ंक्शन परिभाषा से फ़ंक्शन ऑब्जेक्ट के साथ बुलाया जाता है।
फिर – के रूप में अन्य लोगों ने – बताया है इस सज्जाकार स्पष्ट अर्थ में तर्क, डेकोरेटर कारखानों से पारित कर दिया है कि वे का निर्माण और वापसी 'नियमित' डेकोरेटर कार्यों में आता है।
ज्यादातर मामलों में, सजावट करने वालों को या तो एक समारोह या कक्षा के रूप में लागू किया जा सकता है, क्योंकि दोनों पाइथन में कॉल करने योग्य हैं। व्यक्तिगत रूप से मुझे समझने के लिए कार्यों को थोड़ा आसान लगता है और इसलिए निम्न में उस दृष्टिकोण का उपयोग किया जाएगा। दूसरी ओर, फ़ंक्शन दृष्टिकोण मुश्किल हो सकता है क्योंकि इसमें अक्सर एक या अधिक नेस्टेड फ़ंक्शन परिभाषाएं शामिल होती हैं।
यहां बताया गया है कि आप अपने मॉड्यूल में do()
फ़ंक्शन के लिए सजावट कैसे कोड कर सकते हैं। नीचे दिए गए कोड में मैंने परिभाषित किया है कि यह कॉल करने से पहले फ़ंक्शन के तर्कों को प्रिंट करता है।
def do(fn, args=tuple(), kwargs={}, priority=0,
block=False, timeout=0, callback=None, daemon=False):
# show arguments
print ('in do(): fn={!r}, args={}, kwargs={}, priority={},\n'
' block={}, timeout={}, callback={}, daemon={}'
.format(fn.__name__, args, kwargs, priority,
block, timeout, callback, daemon))
# and call function 'fn' with its arguments
print (' calling {}({}, {})'.format(
fn.__name__,
', '.join(map(str, args)) if args else '',
', '.join('{}={}'.format(k, v) for k,v in kwargs.items())
if kwargs else '')
)
fn(*args, **kwargs)
def do_decorator(**do_kwargs):
def decorator(fn):
def decorated(*args, **kwargs):
do(fn, args, kwargs, **do_kwargs)
return decorated
return decorator
@do_decorator(priority=2)
def decoratedTask(arg, dic=42):
print 'in decoratedTask(): arg={}, dic={}'.format(arg, dic)
decoratedTask(72, dic=3)
आउटपुट:
in do(): fn='decoratedTask', args=(72,), kwargs={'dic': 42}, priority=2,
block=False, timeout=0, callback=None, daemon=False
calling decoratedTask(72, dic=3)
in decoratedTask(): arg=72, dic=3
यहाँ कैसे इस जटिल देख सामान काम करता है की एक झटका-दर-झटका खाता है:
बाहरी डेकोरेटर समारोह do_decorator()
, एक और भीतरी डेकोरेटर समारोह जो यह रिटर्न को परिभाषित करता है , यहां रचनात्मक रूप से decorator
नाम दिया गया है।
क्या decorator
करता है क्या परिभाषित कार्यों है कि एक साधारण से सजाया गया है 'कोई तर्क' परिदृश्य — यहाँ जो परिभाषित करने और अभी तक एक और – लेकिन अंतिम – लौटा रहा है नेस्टेड समारोह decorated
कहा जाता है, जो सिर्फ मॉड्यूल के do()
फ़ंक्शन को कॉल करने और करने के लिए होता है do()
फ़ंक्शन के उपयोग के लिए लक्षित किए गए लोगों के साथ, आमंत्रण के बिंदु से कोई भी तर्क दोनों को पास करता है।
यह उपयोग मामला इस तथ्य से कुछ जटिल है कि बाहरी सजावटी और सजाए जाने वाले कार्यों में कीवर्ड तर्क हैं। यह सुनिश्चित करने के लिए अतिरिक्त देखभाल की आवश्यकता है कि प्रत्येक के लिए कीवर्ड के नाम अद्वितीय हैं, इसलिए वे संघर्ष नहीं करते हैं (और यह कि फ़ंक्शन में कुछ द्वारा विस्थापन kwargs
तर्क डिफ़ॉल्ट मान अनजाने में बदला नहीं जाता है)।
धन्यवाद इसने इसे और अधिक स्पष्ट बना दिया है। मैं बस उस तरह गहरी घोंसला वाली कार्य परिभाषाओं से भ्रमित हो जाता हूं। मुझे यकीन है कि मैं समझता हूँ। इसे स्वीकार करने से पहले मुझे इसके साथ थोड़ा सा खेलने दो। – Falmarri