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 assert
cek yang dekorator belum digunakan tanpa tanda kurung. Jika sudah, maka kelas yang sedang didekorasi dilewatkan ke msg
parameter dekorator, yang menimbulkan AssertionError
.
@decorate_if
hanya berlaku decorator
jika condition
dievaluasi True
.
The getattr
, callable
tes, dan @decorate_if
digunakan sehingga dekorator tidak pecah jika foo()
metode tidak ada pada kelas yang dihiasi.