2010-10-21 102 views
3

我想装饰一个实际的类,使用此代码:Python类装饰

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

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

如果__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 

回答

11

__init__没有运行,因为object.__new__不知道叫它。如果将其更改为 cls.__call__(*args, **kwargs)或更好,cls(*args, **kwargs),它应该工作。记住一个类是可调用的:调用它会产生一个新的实例。只要调用__new__就会返回一个实例,但不会进行初始化。另一种方法是呼叫__new__,然后手动呼叫__init__,但这只是替代已在__call__中体现的逻辑。

您引用的文档是指从中调用super该类的__new__方法。在这里,你正在从外面打电话,而不是像我已经讨论过的那样用通常的方式。

+1

由于某种原因,我想创建一个实例就关火'__init__'的行为。感谢您的澄清! – 2010-10-21 00:43:41

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"