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

...但它派生object(就像每个现代风格的 Python 类一样),因此第二个示例无法工作(完全独立于MyMixin具有自定义元类)。

于 2010-06-09T05:29:52.740 回答
-1

这里,你是继承父类,而父类已经继承了另一个类,所以不需要继承父类已经继承的类。

例如:

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

会报错,因为A继承了Object类,B继承了A,所以间接B继承了object,所以不需要继承object。. . .

解决方案是从 B 类 ... 参数列表中删除对象类。

于 2014-05-23T13:26:14.067 回答