首页 文章

元类多重继承不一致

提问于
浏览
56

为什么是这样:

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

2 回答

  • -1

    它在元类阶段被诊断为's not a custom-metaclass problem (though it'):

    >>> 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 .

    幸运的是,您不希望这样做 - 子类可能会覆盖基类的某些方法(这是正常的子类所做的;-),并且具有基类"in front"将意味着"shadowing the override away" .

    将基类放在派生类之后是没用的,但至少它是无害的(并且与正常的MRO保证一致) .

    您的第一个课程示例有效,因为 MyMixin 不是从 list 派生的:

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

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

  • 82

    在这里,您继承父类,并且父类已经继承了另一个类,因此不需要继承父类已经继承的类 .

    例如:

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

    它会抛出一个错误,因为A继承了Object类而B继承了A,所以间接B是继承对象,所以不需要继承对象 . . . .

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

相关问题