2009-11-20 7 views
9

ここはPythonセッションです。 (メタクラスが継承されるよう?)サブクラスでメタクラスが呼び出されない

>>> 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__はそれのために呼び出されることを期待し、起きていない2行を、印刷する

答えて

12

問題がありますtypeを呼び出すときにcls引数(メタクラスオブジェクト)が渡されないため、作成され返されたクラスオブジェクトYには、メタクラスZへの参照がありません。

あなたは

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

__new__で最後の行を交換する場合、それは動作します。 がsuperで使用されていても、を引数として提供する必要があります。superはアンバインドされたメソッドを返します(詳細はhereを参照)。スーパー1を使用する代わりに

は使用することができます

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

重要なことは、我々はクラスメソッド__new__cls(私たちのメタクラスオブジェクトZ)を得たということです。より短い形式type(name, bases, attrs)は、cls引数のためにtype自体を埋め込みますが、これは間違いです。このエラーは、間違ったself引数を持つインスタンスメソッドを呼び出すのと同様です。

superを使用することをお勧めします。より良いスタイルです。

+2

ああ、そうです。しかし、 'super。(Z、cls).__ new__'を' type .__ class __と同じにするべきではありません。新しい 'whisは' type .__ new__'と同じです。これは 'type'で新しいクラスを作るのと同じでしょうか? – agiliq

+2

それは実際には同じではない、私は今これを私の答えで述べる。 Superは 'type .__ new__'メソッドを呼び出しますが、適切な' cls'引数を使用することができます。これは 'type'を直接呼び出すだけでは不可能です。 – nikow

関連する問題