Saya setuju warisan lebih cocok untuk masalah yang diajukan.
Saya menemukan pertanyaan ini sangat berguna pada kelas dekorasi, terima kasih semua.
Berikut adalah beberapa contoh lain, berdasarkan jawaban lain, termasuk bagaimana pewarisan mempengaruhi hal-hal di Python 2.7, (dan @wraps , yang memelihara dokumentasi fungsi asli, dll.):
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...
Seringkali Anda ingin menambahkan parameter ke dekorator Anda:
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()
Output:
@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
Saya telah menggunakan fungsi dekorator, karena saya menemukan mereka lebih ringkas. Berikut kelas untuk mendekorasi kelas:
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
Versi yang lebih kuat yang memeriksa tanda kurung itu, dan berfungsi jika metode tidak ada pada kelas yang didekorasi:
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
The assertcek yang dekorator belum digunakan tanpa tanda kurung. Jika sudah, maka kelas yang sedang didekorasi dilewatkan ke msgparameter dekorator, yang menimbulkan AssertionError.
@decorate_ifhanya berlaku decoratorjika conditiondievaluasi True.
The getattr, callabletes, dan @decorate_ifdigunakan sehingga dekorator tidak pecah jika foo()metode tidak ada pada kelas yang dihiasi.