Python 如何让基于类的装饰器为实例方法工作?
调用decorator有两种方法:1)通过传递decorator函数/类Python 如何让基于类的装饰器为实例方法工作?,python,python-2.7,python-3.x,decorator,Python,Python 2.7,Python 3.x,Decorator,调用decorator有两种方法:1)通过传递decorator函数/类 class Foo(object): def __init__(self): self.x = 1 @foo_decorator def bar(self, x): return self.x + x 或者2)通过传递decorator函数/类实例的返回值 class Foo(object): def __init__(self): sel
class Foo(object):
def __init__(self):
self.x = 1
@foo_decorator
def bar(self, x):
return self.x + x
或者2)通过传递decorator函数/类实例的返回值
class Foo(object):
def __init__(self):
self.x = 1
@foo_decorator("args")
def bar(self, x):
return self.x + x
问题是:如果我需要使用基于类的方法实现decorator,那么如何让decorator在这两种情况下都工作
这种实施的一个例子是:
import functools
class FooDecorator(object):
def __init__(self, *args):
if len(args) == 1 and callable(args[0]):
self.f = args[0]
functools.update_wrapper(self, args[0])
else:
self.f = None
def __call__(self, *args, **kwargs):
if self.f is not None:
return self.f(*args, **kwargs)
else:
assert len(args) >= 1 and callable(args[0])
f = args[0]
self.f = f
functools.update_wrapper(self, f)
return self
foo_decorator = FooDecorator
但是,使用以下代码测试此简单实现会产生一些错误:
class Foo1(object):
def __init__(self):
self.x = 1
@foo_decorator
def bar(self, x):
return self.x + x
class Foo2(object):
def __init__(self):
self.x = 1
@foo_decorator("args")
def bar(self, x):
return self.x + x
Foos = [Foo1, Foo2]
for i in range(2):
print(Foos[i].__name__)
f = Foos[i]()
print(f.bar(10))
Traceback (most recent call last):
File "python", line 47, in <module>
File "python", line 13, in __call__
TypeError: bar() missing 1 required positional argument: 'x'
类Foo1(对象):
定义初始化(自):
self.x=1
@富奥装饰师
def条(自身,x):
返回self.x+x
类别2(对象):
定义初始化(自):
self.x=1
@foo_decorator(“args”)
def条(自身,x):
返回self.x+x
Foos=[Foo1,Foo2]
对于范围(2)中的i:
打印(Foos[i]。_名称__)
f=Foos[i]()
印刷品(f.bar(10))
回溯(最近一次呼叫最后一次):
文件“python”,第47行,在
调用中第13行的文件“python”__
TypeError:bar()缺少1个必需的位置参数:“x”
这已经在Python2.7和3.5上进行了测试
感谢您的帮助。请注意,我已经彻底搜索了整个网站,并且已经阅读了以下关于该主题的文章:
decorator
包不支持产生decorator(预初始化decorator对象)的第二种方法。参考和信用:
类方法是(非数据)描述符。如果方法在修饰期间被替换,则必须恢复描述符函数
这对我在Python3上有效<代码>kwargs为简单起见未实现
class Deco:
def __init__(self, *args):
if len(args) == 1 and callable(args[0]):
self._func = args[0]
self._dargs = None
else:
self._func = None
self._dargs = args
def __call__(self, *args):
if self._func is None:
self._func = args[0]
return self
print("decorated with: {}".format(self._dargs))
return self._func(*args)
def __get__(self, obj, type=None):
if obj is None:
return self
def bound_decorated(*args):
return self.__call__(obj, *args)
return bound_decorated
(无论如何,我更喜欢任何更简单的解决方案。)–我建议您决定您的函数是否是decorator,还是返回decorator。如果参数是可选的,则将其设置为@foo_decorator(“args”)
和@foo_decorator()
,但在调用中加入“magic”以确定它是用作decorator还是用作函数似乎有点太复杂(并且难以维护)。