विचार यहाँ प्रस्तावित उत्कृष्ट रहे हैं, लेकिन कुछ नुकसान:
inspect.getouterframes
और args[0].__class__.__name__
सादा कार्यों और स्थिर-तरीकों के लिए उपयुक्त नहीं हैं।
__get__
एक कक्षा में होना चाहिए, जिसे @wraps
द्वारा अस्वीकार कर दिया गया है।
@wraps
स्वयं को निशान छिपाने के लिए बेहतर होना चाहिए।
तो, मैं इस पृष्ठ, लिंक, डॉक्स और अपने खुद के सिर,
से कुछ विचारों को संयोजित कर दिया और अंत में एक समाधान है, सबसे बढ़कर तीन नुकसान का अभाव पाया।
नतीजतन, method_decorator
:
- वर्ग सजाया विधि के लिए बाध्य है जानता है।
functools.wraps()
से अधिक सटीक रूप से सिस्टम विशेषताओं के उत्तर देकर सजावट के निशान छुपाता है।
- यूनिट-परीक्षणों के साथ एक अनबाउंड इंस्टेंस-विधियों, कक्षा-विधियों, स्थिर-विधियों और सादे कार्यों को बाध्य करने के लिए कवर किया गया है।
उपयोग:
pip install method_decorator
from method_decorator import method_decorator
class my_decorator(method_decorator):
# ...
full unit-tests for usage details देखें।
और यहाँ सिर्फ method_decorator
वर्ग के कोड है:
class method_decorator(object):
def __init__(self, func, obj=None, cls=None, method_type='function'):
# These defaults are OK for plain functions
# and will be changed by __get__() for methods once a method is dot-referenced.
self.func, self.obj, self.cls, self.method_type = func, obj, cls, method_type
def __get__(self, obj=None, cls=None):
# It is executed when decorated func is referenced as a method: cls.func or obj.func.
if self.obj == obj and self.cls == cls:
return self # Use the same instance that is already processed by previous call to this __get__().
method_type = (
'staticmethod' if isinstance(self.func, staticmethod) else
'classmethod' if isinstance(self.func, classmethod) else
'instancemethod'
# No branch for plain function - correct method_type for it is already set in __init__() defaults.
)
return object.__getattribute__(self, '__class__')(# Use specialized method_decorator (or descendant) instance, don't change current instance attributes - it leads to conflicts.
self.func.__get__(obj, cls), obj, cls, method_type) # Use bound or unbound method with this underlying func.
def __call__(self, *args, **kwargs):
return self.func(*args, **kwargs)
def __getattribute__(self, attr_name): # Hiding traces of decoration.
if attr_name in ('__init__', '__get__', '__call__', '__getattribute__', 'func', 'obj', 'cls', 'method_type'): # Our known names. '__class__' is not included because is used only with explicit object.__getattribute__().
return object.__getattribute__(self, attr_name) # Stopping recursion.
# All other attr_names, including auto-defined by system in self, are searched in decorated self.func, e.g.: __module__, __class__, __name__, __doc__, im_*, func_*, etc.
return getattr(self.func, attr_name) # Raises correct AttributeError if name is not found in decorated self.func.
def __repr__(self): # Special case: __repr__ ignores __getattribute__.
return self.func.__repr__()
एक जवाब है, लेकिन पाया इस लेख गहराई में http://bit.ly चीजों को कवर करने/1NsBLmx – apcelent