2009-11-20 60 views
9

這是一個python會話。Metaclass不在子類中調用

>>> class Z(type): 
    def __new__(cls, name, bases, attrs): 
     print cls 
     print name 
     return type(name, bases, attrs) 
...  
>>> class Y(object): 
    __metaclass__ = Z 
...  
<class '__main__.Z'> 
Y 
>>> class X(Y): 
...  pass 
... 
>>> class W(Y): 
...  __metaclass__ = Z 
...  
<class '__main__.Z'> 
W 
>>> 

後我定義類XI預計Z._new__被調用它,並打印兩行,這是不會發生,(如元類被繼承?)

回答

12

的問題是當調用type時,不會傳遞cls參數(它是元類對象),因此創建並返回的類對象Y不具有對元類Z的任何引用。

如果用

return super(Z, cls).__new__(cls, name, bases, attrs) 

替換__new__的最後一行,然後它工作。請注意,即使cls用於super我們仍然必須提供cls作爲參數,因爲super此處返回未綁定方法(有關更多信息,請參閱here)。

作爲替代使用超級一個可以使用:

return type.__new__(cls, name, bases, attrs) 

重要的是,我們給cls(我們的元類對象Z)的類方法__new__。較短的形式type(name, bases, attrs)填充type本身的cls參數,這當然是錯誤的。該錯誤類似於使用錯誤的self參數調用實例方法。

我更喜歡使用super,因爲這是更好的風格。

+2

啊,好的,那個工作。但是不應該'返回super(Z,cls).__ new__'等價於'type .__ class __。new' whis等價於'type .__ new__',它應該和'type'創建一個新類相同? – agiliq 2009-11-21 06:17:08

+2

這實際上是不一樣的,我現在在我的回答中解決這個問題。 Super會調用'type .__ new__'方法,但是我們可以使用正確的'cls'參數,如果我們直接調用'type',這是不可能的。 – nikow 2009-11-21 09:24:07