有人能解释一下为什么下面的代码不起作用吗?我试图让一个类装饰器来提供新的__repr__和__init__方法,如果我用它来修饰一个类,那么似乎只定义了repr方法。我设法修复了最初的问题,方法是让修饰器对原始类进行破坏性修改,而不是创建一个新类(例如,它定义了新方法,然后只使用cl.__init__ = __init__覆盖它们)。现在我只是好奇为什么基于子类的尝试不起作用。
def higherorderclass(cl):
@functools.wraps(cl)
class wrapped(cl):
def __init__(self, *args, **kwds):
print 'in wrapped init'
super(wrapped, self).__init__(*args, **kwds)
def __repr__(self):
return 'in wrapped repr'
return wrapped发布于 2013-11-26 22:47:18
第一个问题是您使用的是旧风格的类。(也就是说,不继承object、另一个内置类型或另一个新样式类的类。)在旧式类中,特殊方法查找的工作方式不同。实际上,您不想了解它是如何工作的,只需要使用新样式的类就行了。
但是接下来会遇到下一个问题:首先,functools.wraps不能在类上工作。使用新的样式类,您将得到某种类型的AttributeError;对于旧的类,事情只是在不同的方面默默地失败。您也不能只显式地使用update_wrapper。问题是,您正在尝试替换类的属性,这些属性是不可写的,而且没有(直接的)方法。
如果您使用新的样式类,并且不尝试使用wraps,那么一切都很好。
发布于 2013-11-26 22:49:09
删除@functools.wraps()装饰符,这只适用于函数装饰器。对于一个新样式的类,您的装饰器在以下方面失败:
>>> @higherorderclass
... class Foo(object):
... def __init__(self):
... print 'in foo init'
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 3, in higherorderclass
File "/Users/mj/Development/Library/buildout.python/parts/opt/lib/python2.7/functools.py", line 33, in update_wrapper
setattr(wrapper, attr, getattr(wrapped, attr))
AttributeError: attribute '__doc__' of 'type' objects is not writable没有@functools.wraps()行,您的装饰器就能正常工作:
>>> def higherorderclass(cl):
... class wrapped(cl):
... def __init__(self, *args, **kwds):
... print 'in wrapped init'
... super(wrapped, self).__init__(*args, **kwds)
... def __repr__(self):
... return 'in wrapped repr'
... return wrapped
...
>>> @higherorderclass
... class Foo(object):
... def __init__(self):
... print 'in foo init'
...
>>> Foo()
in wrapped init
in foo init
in wrapped reprhttps://stackoverflow.com/questions/20229532
复制相似问题