どうしてこれなの:
class MyType(type):
def __init__(cls, name, bases, attrs):
print 'created', cls
class MyMixin:
__metaclass__ = MyType
class MyList(list, MyMixin): pass
さて、期待どおりに動作します:
created <class '__main__.MyMixin'>
created <class '__main__.MyList'>
しかしこれは:
class MyType(type):
def __init__(cls, name, bases, attrs):
print 'created', cls
class MyMixin:
__metaclass__ = MyType
class MyObject(object, MyMixin): pass
大丈夫ではなく、こうして爆破しますか?:
created <class '__main__.MyMixin'>
Traceback (most recent call last):
File "/tmp/junk.py", line 11, in <module>
class MyObject(object, MyMixin): pass
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution
order (MRO) for bases object, MyMixin
これはカスタムメタクラスの問題ではありません(ただし、メタクラスの段階ではdiagnosedです)。
>>> class Normal(object): pass
...
>>> class MyObject(object, Normal): pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution
order (MRO) for bases object, Normal
そして問題はこれと同じです:
>>> class Derived(Normal): pass
...
>>> class Ok(Derived, Normal): pass
...
>>> class Nope(Normal, Derived): pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
Cannot create a consistent method resolution
order (MRO) for bases Normal, Derived
つまり、基本クラスから派生クラスを続けて複数継承することはできません。通常のMRO制約/保証を満たす一貫したMROを定義することは不可能です。
幸い、あなたはwantを行わない-サブクラスはおそらく基本クラスのいくつかのメソッドをオーバーライドします(これは通常のサブクラスdo ;-)をオーバーライドし、 「前」のクラスは、「オーバーライドをシャドウイングする」ことを意味します。
基本クラスを置くafter派生したクラスはほとんど役に立ちませんが、少なくとも無害です(そして通常のMRO保証と一致しています)。
MyMixin
はnotがlist
から派生しているため、コースの最初の例は機能します。
>>> MyMixin.__mro__
(<class '__main__.MyMixin'>, <type 'object'>)
...しかしisはobject
から派生しているため(すべてのモダンスタイルPythonクラスと同様))、2番目の例は機能しません( MyMixin
カスタムメタクラスを持つ)。