2011-09-20 61 views
4

我一直在搞Python的黑暗藝術,並有一些我想幫助理解。鑑於一類Foo,這裏的某些方面,我試圖從它繼承:提供FooMetaclass衝突,多繼承和實例作爲父

  1. class A(Foo) —作品,unsurprizingly
  2. class B(Foo()) —作品具有適當__new__方法(我公司提供)
  3. class C(Foo(), Foo) —作品,在與B相同的條件下
  4. class D(Foo, Foo()) —給出了着名的元類e rror:

    Traceback (most recent call last):
       File "test.py", line 59, in
            class D(Foo, Foo()):
    TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

What exactly is it that causes this conflict? When I inherit from (Foo(), Foo) (instance first, class second) it works, but when I inherit from (Foo, Foo()) (class first, instance second), it doesn't.

回答

5

當你「從一個實例中固有的」,你真正在做的是一種使用元類的奇怪方式。通常,類對象是type的實例。在上述B類的情況下,它繼承自Foo的實例。這正是如果你定義一個類爲Foo作爲其元類,然後從中繼承的類。

所以我對這裏發生的事情的猜測是Python正在處理反向MRO順序中的基類。

C類作品因爲要處理的第一個父類是Foo,其類別爲type。這意味着D的元類必須是type或其某些子類。然後Foo()被處理,其類別是Foo,這是type的子類,所以一切都很好。

D類失敗,因爲要處理的第一個父類是Foo(),它設置D具有Foo(或子類)元類的約束。然後Foo出現,其類別type而不是Foo的子類。

這是一個完整的猜測,但您可以嘗試查看元類的Python文檔是否需要當您從兩個具有不同元類的類繼承時,其中涉及的元類具有子類型關係,並將它們放入特定訂購。

+0

你說得對。順便說一下,「MRO訂單」是什麼意思? –

+1

@Paul MRO是「方法解析順序」,它是在查找方法/屬性時檢查類及其父項的順序。我的直覺就是,因爲第一個父代中的方法'重寫'了第二個中的方法,Python會處理第二個,然後處理第一個。 – Ben