ฉันยอมรับว่าการสืบทอดเป็นสิ่งที่ดีกว่าสำหรับปัญหาที่เกิดขึ้น
ฉันพบว่าคำถามนี้มีประโยชน์มากสำหรับชั้นเรียนตกแต่งขอบคุณทุกคน
นี่คือตัวอย่างอีกสองสามตัวอย่างจากคำตอบอื่น ๆ รวมถึงการสืบทอดส่งผลกระทบต่อสิ่งต่างๆใน Python 2.7 อย่างไร (และ@wrapsซึ่งคงไว้ซึ่ง docstring ของฟังก์ชันดั้งเดิมเป็นต้น):
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...
บ่อยครั้งที่คุณต้องการเพิ่มพารามิเตอร์ให้กับมัณฑนากรของคุณ:
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()
วิธีการไม่ได้อยู่ในระดับที่ถูกการตกแต่ง