元类多重继承不一致

2024-03-29 05:47:19 发布

您现在位置:Python中文网/ 问答频道 /正文

为什么:

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

Tags: nameobjectinitmaindeftypepassattrs
2条回答

在这里,您正在继承父类,而父类已经继承了另一个类,因此不需要继承父类已经继承的类。

例如:

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

它将抛出一个错误,因为A继承类对象,而B继承A,所以间接地B继承对象,所以不需要继承对象。 . . .

解决方法是从类B中移除对象类。。。参数列表。

这不是一个自定义的元类问题(尽管在元类阶段诊断为):

>>> 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'>)

…但是它是从object派生的(就像所有现代风格的Python类一样),所以第二个示例不能工作(完全独立于MyMixin具有自定义元类)。

相关问题 更多 >