元类多重继承不一致

发布于 2024-09-05 01:26:24 字数 897 浏览 3 评论 0原文

为什么这样:

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

Why is this:

class MyType(type):
    def __init__(cls, name, bases, attrs):
        print 'created', cls
class MyMixin:
    __metaclass__ = MyType
class MyList(list, MyMixin): pass

okay, and works as expected:

created <class '__main__.MyMixin'>
created <class '__main__.MyList'>

But this:

class MyType(type):
    def __init__(cls, name, bases, attrs):
        print 'created', cls
class MyMixin:
    __metaclass__ = MyType
class MyObject(object, MyMixin): pass

Is not okay, and blows up thusly?:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

永不分离 2024-09-12 01:26:24

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

>>> 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 完全独立)。

It's not a custom-metaclass problem (though it's diagnosed at metaclass stage):

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

and the problem's just the same as this one:

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

i.e., can't multiply inherit from a base class followed by a derived class -- it's impossible to define a consistent MRO that satisfies the usual MRO constraints/guarantees.

Fortunately, you don't want to do that -- the subclass presumably overrides some method of the base class (that's what normal subclasses do;-), and having the base class "in front" would mean "shadowing the override away".

Putting the base class after the derived one is pretty useless, but at least it's innocuous (and consistent with normal MRO guarantees).

Your first example of course works because MyMixin is not derived from list:

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

...but it is derived from object (like every modern-style Python class), so the second example cannot work (quite independently from MyMixin having a custom metaclass).

陪你搞怪i 2024-09-12 01:26:24

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

例如:

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

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


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

Here, you are inheriting the parent class, and the parent class is already inheriting another class, so there is no need to inherit the class that the parent class already inherited.

For example:

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

It will throw an error because A is inheriting the class Object and B is inheriting the A, so indirectly B is inheriting object, so there is no need to inherit object.
.
.
.

The Solution is to just remove the object class from class B ... arguments list.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文