【发布时间】:2014-03-12 19:40:45
【问题描述】:
我试图让基于类的装饰器保持原始包装函数的 repr() 行为(以匹配 functools.wraps 装饰器在函数上的工作方式)。我正在使用 python 3.3。
首先我尝试了 functools:
import functools
class ClassBasedDecorator():
def __init__(self, fn):
self.fn = fn
functools.update_wrapper(self, fn)
def __call__(self, *args, **kwargs):
self.fn(*args, **kwargs)
@ClassBasedDecorator
def wrapped(text):
pass
但是当我在装饰函数上调用repr() 时,我得到:
>>> repr(wrapped)
'<__main__.ClassBasedDecorator object at 0x2d8860b6850>'
很好,所以我尝试自定义我的装饰器的__repr__方法,它应该被repr()调用。
再次使用 functools:
class ClassBasedDecorator():
def __init__(self, fn):
self.fn = fn
functools.update_wrapper(
self, fn,
assigned=functools.WRAPPER_ASSIGNMENTS + ('__repr__',)
)
def __call__(self, *args, **kwargs):
self.fn(*args, **kwargs)
不会改变输出,但会发生一些有趣的事情:
>>> repr(wrapped)
'<__main__.ClassBasedDecorator object at 0x2d8860b69d0>'
>>> wrapped.__repr__()
'<function wrapped at 0x2d8860a9710>'
显式设置装饰器实例的__repr__方法效果相同。
经过更多测试,我推断出repr(instance) 实际上调用了instance.__class__.__repr__(instance)。因此,实例的重写 __repr__ 方法永远不会被调用。
所以这是我的问题:
- 为什么
repr(instance)调用instance.__class__.__repr__(instance)而不是instance.__repr__()?还是我错过了什么? - 您如何将
functools.wraps对基于函数的装饰器所做的完全复现为基于类的装饰器(包括更改repr()对装饰函数的调用的结果)?
【问题讨论】:
标签: python python-3.x decorator python-decorators repr