2011-09-20 52 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:

現在,我想補充__new__爲ProductClass:

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) 

它是多彩的__call__的責任,呼籲ProductClass的__new____init__

回答

4

是的 - 這是Meta.__call__撥打ProductClass.__init__(或不是,視情況而定)。

引述documentation

例如限定元類 定製__call__()方法允許自定義行爲當類被調用時,例如並不總是 創建一個新的實例。

該頁面還提到一種情況,元類的__call__可能會返回一個不同的類的實例(即不ProductClass在你的例子)。在這種情況下,自動呼叫ProductClass.__init__顯然不合適。

+0

什麼,如果我得到了一個ProductClass「__new__」? Meta的「__call__」調用ProductClass的「__new__」和「__init__」?看我的更新。 – Alcott

+0

顯然,Meta的「__call__」在ProductClass的「__new__」之前被首先調用。 – Alcott

+0

問題是,需要'Meta .__ call__'來調用'ProductClass .__ new__'和'ProductClass .__ init__'。通常,'type .__ call__'是爲你做的,但是當你定義'Meta .__ call__'時,你會覆蓋這個行爲,這意味着除非你這麼做,否則它不會被執行。所以,你需要自己調用'__new__'和'__init__',或者調用類似'.__ call __(cls,* args)'的東西。 –

6

有延伸的方法和覆蓋它,你只是在你的元類Meta沒有叫,因爲你定義了__call__方法和你沒有調用父__call__首要之間的OOP的差異。有你想你必須擴展__call__方法通過調用父類的方法行爲:

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