2011-09-20 8 views
5

は、私がメタクラスだと言う:次のようにメタクラスの "__call__" と製品・クラスの "__init__"

class Meta(type): 
    def __call__(cls, *args): 
     print "Meta: __call__ with", args 

class ProductClass(object): 
    __metaclass__ = Meta 
    def __init__(self, *args): 
     print "ProductClass: __init__ with", args 

p = ProductClass(1) 

出力を:

Meta: __call__ with (1,) 

質問:

をされていない理由ProductClassの__init__がトリガーされましたか? Metaの__call__のためだけですか?

UPDATE:今

、私はProductClassため__new__を追加します。

class ProductClass(object): 
     __metaclass__ = Meta 
     def __new__(cls, *args): 
      print "ProductClass: __new__ with", args 
      return super(ProductClass, cls).__new__(cls, *args) 
     def __init__(self, *args): 
      print "ProductClass: __init__ with", args 

p = ProductClass(1) 

はProductClassの__new____init__を呼び出すためのMetaの__call__の責任ですか?

答えて

4

はい - ProductClass.__init__に電話するには、Meta.__call__までです(場合によってはそうでない場合もあります)。 documentationを引用する

:クラスが呼び出されたときにメタクラス でカスタム__call__()方法を定義

例えば、カスタム動作を可能にする、例えば新しいインスタンスを作成することは常にありません。

そのページはメタクラスの__call__は、異なるクラスのインスタンスを返すことができるシナリオを言及(すなわちないProductClassあなたの例で)。このシナリオでは、ProductClass.__init__に自動的に電話するのは明らかに不適切です。

+0

ProductClassで "__new__"を取得した場合はどうすればよいですか? Metaの "__call__"はProductClassの "__new__"と "__init__"を呼び出しますか?私のUPDATEを見てください。 – Alcott

+0

そして明らかに、Metaの "__call__"は、ProductClassの "__new__"の前に最初に呼び出されます。 – Alcott

+0

問題は 'ProductClass .__ new__'と' ProductClass .__ init__'を呼び出すために 'Meta .__ call__'が必要であるということです。通常、 'type .__ call__'はこれを行いますが、' Meta .__ call__'を定義するとその動作をオーバーライドします。そうしないと実行されません。したがって、自分で '__new__'と' __init__'を呼び出すか、 'type .__ call__(cls、* args)'のようなものを呼び出す必要があります。 –

6

メソッドの拡張とオーバーライドの間にOOPの違いがあります。__call__メソッドを定義し、親を__call__と呼んでいないため、メタクラスMetaで行った処理がオーバーライドと呼ばれます。

class Meta(type): 
    def __call__(cls, *args): 
     print "Meta: __call__ with", args 
     return super(Meta, cls).__call__(*args) 
関連する問題