मैं मानता हूं कि विरासत समस्या के लिए बेहतर फिट है।
मुझे यह सवाल वास्तव में सजाया गया है हालांकि सजाने वाले वर्गों पर, धन्यवाद।
def dec(klass):
old_foo = klass.foo
@wraps(klass.foo)
def decorated_foo(self, *args ,**kwargs):
print('@decorator pre %s' % msg)
old_foo(self, *args, **kwargs)
print('@decorator post %s' % msg)
klass.foo = decorated_foo
return klass
@dec # no parentheses
class Foo...
अक्सर आप अपने डेकोरेटर के लिए मानकों को जोड़ना चाहते हैं: यहाँ एक और कुछ उदाहरण सहित कैसे विरासत अजगर 2.7, (और @wraps है, जो मूल कार्य के docstring, आदि का कहना है) में चीजों को प्रभावित करता है अन्य उत्तर, के आधार पर दिया गया है:
from functools import wraps
def dec(msg='default'):
def decorator(klass):
old_foo = klass.foo
@wraps(klass.foo)
def decorated_foo(self, *args ,**kwargs):
print('@decorator pre %s' % msg)
old_foo(self, *args, **kwargs)
print('@decorator post %s' % msg)
klass.foo = decorated_foo
return klass
return decorator
@dec('foo decorator') # you must add parentheses now, even if they're empty
class Foo(object):
def foo(self, *args, **kwargs):
print('foo.foo()')
@dec('subfoo decorator')
class SubFoo(Foo):
def foo(self, *args, **kwargs):
print('subfoo.foo() pre')
super(SubFoo, self).foo(*args, **kwargs)
print('subfoo.foo() post')
@dec('subsubfoo decorator')
class SubSubFoo(SubFoo):
def foo(self, *args, **kwargs):
print('subsubfoo.foo() pre')
super(SubSubFoo, self).foo(*args, **kwargs)
print('subsubfoo.foo() post')
SubSubFoo().foo()
आउटपुट:
@decorator pre subsubfoo decorator
subsubfoo.foo() pre
@decorator pre subfoo decorator
subfoo.foo() pre
@decorator pre foo decorator
foo.foo()
@decorator post foo decorator
subfoo.foo() post
@decorator post subfoo decorator
subsubfoo.foo() post
@decorator post subsubfoo decorator
मैं एक समारोह डेकोरेटर का उपयोग किया है, के रूप में मैं उन्हें अधिक संक्षिप्त पाते हैं। यहां कक्षा को सजाने के लिए एक वर्ग है:
class Dec(object):
def __init__(self, msg):
self.msg = msg
def __call__(self, klass):
old_foo = klass.foo
msg = self.msg
def decorated_foo(self, *args, **kwargs):
print('@decorator pre %s' % msg)
old_foo(self, *args, **kwargs)
print('@decorator post %s' % msg)
klass.foo = decorated_foo
return klass
एक और अधिक मजबूत संस्करण है कि उन कोष्ठकों के लिए जाँच करता है, और काम करता है तरीकों से सजाया वर्ग पर मौजूद नहीं हैं:
from inspect import isclass
def decorate_if(condition, decorator):
return decorator if condition else lambda x: x
def dec(msg):
# Only use if your decorator's first parameter is never a class
assert not isclass(msg)
def decorator(klass):
old_foo = getattr(klass, 'foo', None)
@decorate_if(old_foo, wraps(klass.foo))
def decorated_foo(self, *args ,**kwargs):
print('@decorator pre %s' % msg)
if callable(old_foo):
old_foo(self, *args, **kwargs)
print('@decorator post %s' % msg)
klass.foo = decorated_foo
return klass
return decorator
assert
जांच करता है कि सजावटी को बिना किसी ब्रांड्स के इस्तेमाल किया गया है।यदि यह है, तो सजाया जाने वाला वर्ग सजावट के msg
पैरामीटर को पास कर दिया गया है, जो AssertionError
उठाता है।
@decorate_if
decorator
लागू होता है यदि condition
True
पर मूल्यांकन करता है।
getattr
, callable
परीक्षण, और @decorate_if
उपयोग किया जाता है ताकि डेकोरेटर अगर foo()
विधि वर्ग सजाया जा रहा है पर मौजूद नहीं है नष्ट नहीं होती है।
हालांकि यह उपयोगी है, पाइथन सजावट सजावटी पैटर्न से अलग हैं। मुझे लगता है कि एक दुर्भाग्यपूर्ण नाम। हालांकि, मैं इस तरह से जा रहा हूँ। धन्यवाद। –
@ रॉबर्ट गौलैंड: बहुत राजनयिक। –