Python类装饰器

时间:2010-10-21 00:26:36

标签: python decorator

我正在尝试使用以下代码修饰一个实际的类:

def my_decorator(cls):
    def wrap(*args, **kw):
        return object.__new__(cls)
    return wrap

@my_decorator
class TestClass(object):
    def __init__(self):
        print "__init__ should run if object.__new__ correctly returns an instance of cls"


test = TestClass() # shouldn't TestClass.__init__() be run here?

我没有错误,但我也没有看到来自TestClass.__init__()的消息。

根据the docs for new-style classes

  

典型的实现通过使用带有适当参数的__new__()调用超类的super(currentclass, cls).__new__(cls[, ...])方法创建类的新实例,然后在返回之前根据需要修改新创建的实例。

     

如果__new__()返回cls的实例,那么将调用新实例的__init__()方法,如__init__(self[, ...]),其中self是新实例,其余参数与传递给__new__()

为什么__init__未运行的任何想法?

另外,我试图像这样致电__new__

return super(cls.__bases__[0], cls).__new__(cls)

但会返回TypeError

TypeError: super.__new__(TestClass): TestClass is not a subtype of super

2 个答案:

答案 0 :(得分:11)

__init__未运行,因为object.__new__无法调用它。如果你改成它 cls.__call__(*args, **kwargs),或更好,cls(*args, **kwargs),它应该有用。请记住,类是可调用的:调用它会生成一个新实例。只是调用__new__会返回一个实例,但不会进行初始化。另一种方法是调用__new__,然后手动调用__init__,但这只是替换__call__中已经包含的逻辑。

您引用的文档是指在类的super方法中从调用__new__。在这里,你是从外面调用它,而不是像我已经讨论过的那样。

答案 1 :(得分:0)

无法告诉您原因,但此黑客确实运行__init__

def my_decorator(cls):
    print "In my_decorator()"
    def wrap(*args, **kw):
        print "In wrap()"
        return cls.__init__(object.__new__(cls), *args, **kw)
    return wrap

@my_decorator
class TestClass(object):
    def __init__(self):
        print "__init__ should run if object.__new__ correctly returns an instance of cls"