2017-10-01 6 views
0

以下のコードでは、オブジェクトベースのメタクラスがメタクラスの競合例外を発生させるのはなぜですか?オブジェクトベースのメタクラスがメタクラスの競合を引き起こすのはなぜですか?

「メタクラスの競合:派生クラスのメタクラスは、そのすべての拠点のメタクラスの(非厳密)サブクラスでなければなりません」:

class M_A(object): pass 
class A(object, metaclass = M_A): pass 

だから、別のコードを実行し

class M_A(list): pass 
class A(object, metaclass = M_A): pass 

私はcpythonが上記のコードを次のように解釈することを理解しています:

A = M_A.__new__(M_A, 'A', (object,), {}) 

Aの基底クラスはオブジェクトであり、どのクラスもオブジェクトのサブクラスです。このエラーはとても奇妙です。 私の何が悪いですか?

+1

は 'M_A'はA''のいずれかの基底クラスのメタクラスのサブクラスではありません。 'クラスM_A(型):パス'がおそらく動作します。 – vaultah

+0

私が混乱するのは、Aの基底クラスが* object *であり、どんなクラスも* object *のサブクラスであるということです。 M_A(リスト)は、Aの基本クラスのメタクラスのサブクラスですか?それはそうですね。 – ahui

+0

@ahui 'M_A(list)'は 'object'のサブクラスです、はい。しかし、それはエラーメッセージについてではありません。 'M_A'は' object'の_metaclass_のサブクラスでなければなりません。これは 'type'です。 –

答えて

3

のは、このエラーメッセージを詳しく見てみましょう:

メタクラスの競合:派生クラスのメタクラスは、そのすべての拠点のメタクラスの(非厳密)サブクラスでなければなりません

これは少し混乱して、それでは、何が何を見てみましょう:

  • 「派生クラス」がです3210。
  • 「派生クラスのメタクラス」Aは、M_Aです。
  • Aの基底クラスがobjectであり、従って『すべての塩基のメタクラスは』 typeある - typeobjectであるためのメタクラス。

これが問題である - objectのメタクラスはtypeですが、AのメタクラスはM_Aです。 M_Atypeのサブクラスではないので、pythonはAに使用するメタクラスを知らず、エラーをスローします。 typeM_Aの親クラスを変更、この問題を解決するには


class M_A(type): pass 
class A(object, metaclass = M_A): pass 

# no errors thrown 
関連する問題