58

どうしてこれなの:

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
4

2 に答える 2

83

これはカスタムメタクラスの問題ではありません(メタクラスの段階で診断されますが):

>>> 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を定義することはできません。

幸いなことに、あなたはそれをしたくありません-サブクラスはおそらく基本クラスのいくつかのメソッドをオーバーライドします(それは通常のサブクラスが行うことです;-)、そして基本クラスを「前に」持つことは「オーバーライドをシャドウイングする」ことを意味します。

基本クラスを派生クラスの後に置くことはかなり役に立たないが、少なくとも無害である(そして通常のMRO保証と一致している)。

もちろん、最初の例は、から派生したものMyMixinではないlistため、機能します。

>>> MyMixin.__mro__
(<class '__main__.MyMixin'>, <type 'object'>)

...しかし、これは(すべてのモダンスタイルのPythonクラスと同様に)派生しているためobject、2番目の例は機能しません(MyMixinカスタムメタクラスを持つこととはまったく独立しています)。

于 2010-06-09T05:29:52.740 に答える
-1

ここでは、親クラスを継承しており、親クラスはすでに別のクラスを継承しているため、親クラスがすでに継承しているクラスを継承する必要はありません。

例えば:

class A(object):
.
.
class B(object, A):
.
.

AはクラスObjectを継承し、BはAを継承しているため、エラーがスローされます。間接的にBはオブジェクトを継承しているため、オブジェクトを継承する必要はありません。。。。

解決策は、クラスB...引数リストからオブジェクトクラスを削除することです。

于 2014-05-23T13:26:14.067 に答える