我希望类中的函数将其返回值存储在某些数据结构中。为此,我想使用装饰器:
results = []
instances = []
class A:
def __init__(self, data):
self.data = data
@decorator
def f1(self, a, b):
return self.data + a + b
@decorator
def f2(self, a):
return self.data + a + 1
x = A(1)
x.f1(1, 2)
x.f2(3)
print(results)
问题是,如何实现此装饰器。
主要思想如下:
class Wrapper:
def __init__(self, func):
self.func = func
def __call__(self, *args):
res = self.func(*args)
results.append(res)
instances.append(args[0])
def decorator(func):
return Wrapper(func)
但是随后我收到一条错误消息:
TypeError: f1() missing 1 required positional argument: 'b'
此问题与其他人的问题(How to decorate a method inside a class?,Python functools.wraps equivalent for classes)类似,但在我的情况下,放置@functools.wraps
或致电@functools.update_wrapped()
的位置尚不清楚
答案 0 :(得分:3)
我想这就是你要的。
In [8]: from functools import wraps
...: results = []
...: instances = []
...:
...: class A:
...: def __init__(self, data):
...: self.data = data
...:
...: def decorator(f):
...: @wraps(f)
...: def inner(*args, **kwargs):
...: retval = f(*args, **kwargs)
...: results.append(retval)
...: return retval
...: return inner
...:
...:
...: @decorator
...: def f1(self, a, b):
...: return self.data + a + b
...:
...: @decorator
...: def f2(self, a):
...: return self.data + a + 1
...:
In [9]: a = A(3)
In [10]: a.f1(2,3)
Out[10]: 8
In [11]: results
Out[11]: [8]
Decorator不必在类中,但是在您需要访问类实例本身时,它很方便。您可以将其取出而无需更改任何代码。
In [8]: from functools import wraps
...: results = []
...: instances = []
...: def decorator(f):
...: @wraps(f)
...: def inner(*args, **kwargs):
...: retval = f(*args, **kwargs)
...: results.append(retval)
...: return retval
...: return inner
...:
...: class A:
...: def __init__(self, data):
...: self.data = data
...:
...:
...:
...: @decorator
...: def f1(self, a, b):
...: return self.data + a + b
...:
...: @decorator
...: def f2(self, a):
...: return self.data + a + 1
...:
In [9]: a = A(3)
In [10]: a.f1(2,3)
Out[10]: 8
In [11]: results
Out[11]: [8]
将起作用。
答案 1 :(得分:3)
如果您想在课堂外有Wrapper
,可以实现__get__
方法(descriptor protocol):
from functools import partial
class Wrapper:
def __init__(self, func):
self.func = func
def __get__(self, obj, type=None):
bound_f = partial(self.__call__, obj)
return bound_f
def __call__(self, other_self, *args, **kwargs):
res = self.func(other_self, *args, **kwargs)
results.append(res)
return res
def decorator(func):
return Wrapper(func)
results = []
class A:
def __init__(self, data):
self.data = data
@decorator
def f1(self, a, b):
return self.data + a + b
@decorator
def f2(self, a):
return self.data + a + 1
x = A(1)
x.f1(1, 2)
x.f2(3)
print(results)
打印:
[4, 5]