[英]Add decorator to a method from inherited class?
I want to inherit from class just to add decorators to its methods. 我想从类继承,只是将装饰器添加到其方法。
Is there a shortcut to do this without redefining each base class method? 有没有在不重新定义每个基类方法的情况下执行此操作的捷径?
Sure, you can do this dynamically. 当然,您可以动态地执行此操作。 Suppose you have some class:
假设您有一些课程:
>>> class Foo:
... def bar(self): print('bar')
... def baz(self): print('baz')
...
And a decorator: 还有一个装饰器:
>>> def deco(f):
... def wrapper(self):
... print('decorated')
... return f(self)
... return wrapper
...
Then simply inherit: 然后简单地继承:
>>> class Foo2(Foo):
... pass
...
Then loop over your original class, and apply the decorator to your new child-class: 然后遍历您的原始类,并将装饰器应用于新的子类:
>>> for name, attr in vars(Foo).items():
... if callable(attr):
... setattr(Foo2, name, deco(attr))
...
So... 所以...
>>> x = Foo2()
>>> x.bar()
decorated
bar
>>> x.baz()
decorated
baz
Now, using if callable(attr)
might not be restrictive enough. 现在,使用
if callable(attr)
可能不够严格。 You might want to ignore "dunder" methods, so instead: 您可能要忽略“ dunder”方法,因此:
for name, attr in vars(Foo):
if callable(attr) and not name.startswith('__'):
setattr(Foo2, name, attr)
might be more appropriate. 可能更合适。 Depends on your use-case.
取决于您的用例。
And just for fun, here we can also use the type
constructor: 只是为了好玩,在这里我们还可以使用
type
构造函数:
In [17]: class Foo:
...: def bar(self): print('bar')
...: def baz(self): print('baz')
...:
In [18]: def deco(f):
...: def wrapper(self):
...: print('decorated')
...: return f(self)
...: return wrapper
...:
In [19]: Foo3 = type(
...: 'Foo3',
...: (Foo,),
...: {name:deco(attr) for name, attr in vars(Foo).items() if callable(attr)}
...: )
In [20]: y = Foo3()
In [21]: y.bar()
decorated
bar
In [22]: y.baz()
decorated
baz
You can use a class decorator to encapsulate the whole work 您可以使用类装饰器来封装整个工作
Example code: 示例代码:
def deco(func):
"""Function decorator"""
def inner(*args, **kwargs):
print("decorated version")
return func(*args, **kwargs)
return inner
def decoclass(decorator):
"""Class decorator: decorates public methods with decorator"""
def outer(cls):
class inner(cls):
pass
for name in dir(cls):
if not name.startswith("_"): # ignore hidden and private members
# print("decorating", name) # uncomment for tests
attr = getattr(inner, name)
setattr(inner, name, decorator(attr))
return inner
return outer
class Foo:
"""Sample class""
def foo(self):
return "foo in Foo"
You can then use it: 然后可以使用它:
>>> @decoclass(deco)
class Foo2(Foo):
pass
>>> f = Foo2()
>>> f.foo()
decorated version
'foo in Foo'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.