2010-10-21 160 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"