मान लीजिए मैंने एक डेकोरेटर लिखा है जो कुछ बहुत सामान्य करता है। उदाहरण के लिए, यह सभी तर्कों को एक विशिष्ट प्रकार में परिवर्तित कर सकता है, लॉगिंग कर सकता है, संस्मरण लागू कर सकता है, आदि।
यहाँ एक उदाहरण है:
def args_as_ints(f):
def g(*args, **kwargs):
args = [int(x) for x in args]
kwargs = dict((k, int(v)) for k, v in kwargs.items())
return f(*args, **kwargs)
return g
@args_as_ints
def funny_function(x, y, z=3):
"""Computes x*y + 2*z"""
return x*y + 2*z
>>> funny_function("3", 4.0, z="5")
22
अभी तक सब कुछ ठीक है। हालाँकि, एक समस्या है। सजाया गया फ़ंक्शन मूल फ़ंक्शन के दस्तावेज़ को बनाए नहीं रखता है:
>>> help(funny_function)
Help on function g in module __main__:
g(*args, **kwargs)
सौभाग्य से, वहाँ एक समाधान है:
def args_as_ints(f):
def g(*args, **kwargs):
args = [int(x) for x in args]
kwargs = dict((k, int(v)) for k, v in kwargs.items())
return f(*args, **kwargs)
g.__name__ = f.__name__
g.__doc__ = f.__doc__
return g
@args_as_ints
def funny_function(x, y, z=3):
"""Computes x*y + 2*z"""
return x*y + 2*z
इस बार, फ़ंक्शन नाम और दस्तावेज़ सही हैं:
>>> help(funny_function)
Help on function funny_function in module __main__:
funny_function(*args, **kwargs)
Computes x*y + 2*z
लेकिन अभी भी एक समस्या है: फ़ंक्शन हस्ताक्षर गलत है। सूचना "* args, ** kwargs" बेकार के बगल में है।
क्या करें? मैं दो सरल लेकिन त्रुटिपूर्ण वर्कअराउंड के बारे में सोच सकता हूं:
1 - डॉकस्ट्रिंग में सही हस्ताक्षर शामिल करें:
def funny_function(x, y, z=3):
"""funny_function(x, y, z=3) -- computes x*y + 2*z"""
return x*y + 2*z
नकल की वजह से यह खराब है। हस्ताक्षर अभी भी स्वचालित रूप से उत्पन्न प्रलेखन में ठीक से नहीं दिखाए जाएंगे। फ़ंक्शन को अपडेट करना और डॉकस्ट्रिंग को बदलना या टाइपो बनाने के बारे में भूलना आसान है। [ और हाँ, मैं इस तथ्य से अवगत हूं कि डॉकस्ट्रिंग पहले से ही फ़ंक्शन बॉडी को डुप्लिकेट करता है। कृपया इसे अनदेखा करें; funny_function सिर्फ एक यादृच्छिक उदाहरण है। ]
2 - एक डेकोरेटर का उपयोग न करें, या हर विशिष्ट हस्ताक्षर के लिए एक विशेष उद्देश्य वाले डेकोरेटर का उपयोग करें:
def funny_functions_decorator(f):
def g(x, y, z=3):
return f(int(x), int(y), z=int(z))
g.__name__ = f.__name__
g.__doc__ = f.__doc__
return g
यह ऐसे कार्यों के सेट के लिए ठीक काम करता है जिनमें समान हस्ताक्षर होते हैं, लेकिन यह सामान्य रूप से बेकार है। जैसा कि मैंने शुरुआत में कहा था, मैं पूरी तरह से उदारतापूर्वक सज्जाकारों का उपयोग करने में सक्षम होना चाहता हूं।
मैं एक ऐसे समाधान की तलाश में हूं जो पूरी तरह से सामान्य और स्वचालित हो।
तो सवाल यह है: क्या यह बनाए जाने के बाद सजाए गए फ़ंक्शन हस्ताक्षर को संपादित करने का एक तरीका है?
अन्यथा, क्या मैं एक डेकोरेटर लिख सकता हूं जो फ़ंक्शन हस्ताक्षर को निकालता है और सजाए गए फ़ंक्शन का निर्माण करते समय "* kwargs, ** kwargs" के बजाय उस जानकारी का उपयोग करता है? मैं उस जानकारी को कैसे निकालूं? मुझे सजाए गए फ़ंक्शन का निर्माण कैसे करना चाहिए - निष्पादन के साथ?
कोई अन्य दृष्टिकोण?
inspect.Signature
सजाए गए कार्यों से क्या जोड़ा जाए।