2014-02-09 124 views
2

我有點困惑元繼承的情況下多繼承。Python的metaclasses混淆

考慮下面的代碼:

class MetaClass1(type): 
    def __init__(cls, name, bases, dict_): 
     print "MetaClass1" 

class MetaClass2(type): 
    def __init__(cls, name, bases, dict_): 
     print "MetaClass2" 

class A(object): 
    __metaclass__ = MetaClass1 


class B(object): 
    __metaclass__ = MetaClass2 

class C(A, B): 
    pass 

的這個輸出將是如下:

  1. 「MetaClass1」

  2. 「MetaClass2」

  3. 類型錯誤有關元類衝突,這是預期的,沒有問題毫秒關於這一點。

接下來我會改變一下代碼並執行以下操作:

class MetaClass1(type): 
    def __init__(cls, name, bases, dict_): 
     print "MetaClass1" 

class MetaClass2(MetaClass1): 
    def __init__(cls, name, bases, dict_): 
     print "MetaClass2 inherits" 
     super(MetaClass2, cls).__init__(name, bases, dict_) 

class A(object): 
    __metaclass__ = MetaClass1 


class B(object): 
    __metaclass__ = MetaClass2 

class C(A, B): 
    pass 

這一次的輸出將是:

  1. 「MetaClass1」

  2. 「MetaClass2繼承」

    「MetaClass1」

  3. 「MetaClass2繼承」

    「MetaClass1」

C類的MRO是:

[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <type 'object'>] 

爲什麼C類接收MetaClass2作爲其元類而不是MetaClass1?

回答

5

當決定一個沒有明確指定的類的元類時(例如你的C),Python檢查正在創建的類的所有超類(直接和間接)的元類,並選擇一個元類是所創建類的所有超類的所有元類的子類型。如果沒有這樣的元類,它會產生一個TypeError

在你的例子中,MetaClass2是繼承自C的所有超類的元類的一個元類。

這涵蓋在section 3.3.3.1的語言參考。

+0

謝謝! 這實際上是一個非常聰明的機制。 – Nadav