Python中的高阶类

时间:2013-11-26 22:41:07

标签: python decorator python-decorators

任何人都可以解释为什么以下代码不起作用?我正在尝试创建一个类装饰器来提供新的__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

2 个答案:

答案 0 :(得分:4)

第一个问题是您使用的是旧式课程。 (即,不从object继承的类,另一个内置类型或其他新式类。)特殊方法查找在旧式类中的工作方式不同。真的,你不想学习它是如何工作的;只需使用新式的类。

但是你遇到了下一个问题:functools.wraps首先不适用于类。对于新式课程,您将获得某种AttributeError;对于旧式的课程,事情会以各种方式无声地失败。而且你也不能明确地使用update_wrapper。问题是你试图替换不可写的类的属性,并且没有(直接)方法。

如果您使用新式课程,并且不尝试wraps他们,那么一切正常。

答案 1 :(得分:3)

删除@functools.wraps()装饰器,这仅适用于功能装饰器。使用newstyle类,装饰器失败了:

>>> @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 repr