不是类装饰器,而是装饰器类。
我可以编写一个装饰器函数,它工作正常,但是当我尝试将它作为一个类实现(主要是从嵌套中解决)时,我会陷入自拍状态。这是一个最小的工作示例:
注意装饰器与括号一起使用,如@DecoratorClass()
而不是@DecoratorClass
。这会产生很大的不同。
def decorator_function():
def decorator(fcn):
def wrapper(self, *args):
print('decorator_function wrapper self:', self)
print('decorator_function wrapper args:', args)
return fcn(self, *args)
return wrapper
return decorator
class DecoratorClass:
def __init__(self):
self.fcn = None
def __call__(self, fcn):
self.fcn = fcn
return self.wrapper
def wrapper(self, *args):
print('DecoratorClass wrapper self:', self)
print('DecoratorClass wrapper args:', args)
return self.fcn(*args)
class A:
@decorator_function()
def x(self, *args):
print('A x self:', self)
print('A x args:', args)
return 42
@DecoratorClass()
def y(self, *args):
print('A y self:', self)
print('A y args:', args)
return 43
a = A()
a.x(1, 2)
a.y(1, 2)
这是输出。
decorator_function wrapper self: <mytests.debugme.A object at 0x7fa540d315f8>
decorator_function wrapper args: (1, 2)
A x self: <mytests.debugme.A object at 0x7fa540d315f8>
A x args: (1, 2)
DecoratorClass wrapper self: <mytests.debugme.DecoratorClass object at 0x7fa540d31208>
DecoratorClass wrapper args: (1, 2)
A y self: 1
A y args: (2,)
如您所见,基于类的方法失去了对a
的引用。为了澄清,我希望a.y(1,2)
的结果与a.x(1,2)
相同。
更新@Martijn Pieters
class DecoratorClass:
def __init__(self):
self.fcn = None
def __call__(self, fcn):
self.fcn = fcn
return self.wrapper
def __get__(self, obj, objtype):
"""Support instance methods."""
import functools
return functools.partial(self.__call__, obj)
def wrapper(self, *args):
print('DecoratorClass wrapper self:', self)
print('DecoratorClass wrapper args:', args)
return self.fcn(*args)
a = A()
a.y(1, 2)
输出:
DecoratorClass wrapper self: <mytests.debugme.DecoratorClass object at 0x7fa540d31048>
DecoratorClass wrapper args: (1, 2)
A y self: 1
A y args: (2,)
IOW:标记的重复问题没有可行的答案。