为啥具有对象基础的元类会引发元类冲突?

Posted

技术标签:

【中文标题】为啥具有对象基础的元类会引发元类冲突?【英文标题】:Why does metaclass with object base raise metaclass conflict?为什么具有对象基础的元类会引发元类冲突? 【发布时间】:2018-03-12 16:19:18 【问题描述】:

为什么在下面的代码中带有对象基础的元类会引发元类冲突异常?

“元类冲突:派生类的元类必须是其所有基类的元类的(非严格)子类”

class M_A(object): pass
class A(object, metaclass = M_A): pass

另一个代码也是如此:

class M_A(list): pass
class A(object, metaclass = M_A): pass

我知道cpython会将上面的代码解释为:

A = M_A.__new__(M_A, 'A', (object,), )

让我困惑的是A的基类是object,而任何类都是object的子类。这个错误太奇怪了。 我怎么了?

【问题讨论】:

M_A 不是A 的任何基类的元类的子类。 class M_A(type): pass 可能会起作用。 让我困惑的是A的基类是object,而任何类都是object的子类。 M_A(list) 是 A 的任何基类的元类的子类吗?我认为是。 @ahui M_A(list)object 的子类,是的。但这不是错误消息的内容。 M_A 必须是object元类 的子类,即type 【参考方案1】:

让我们仔细看看这个错误信息:

元类冲突:派生类的元类必须是其所有基类的元类的(非严格)子类

这有点令人困惑,所以我们来看看是什么:

“派生类”A“派生类的元类” AM_AA 的基类是 object,因此 “所有基类的元类”type - 因为 typeobject 的元类。

这就是问题所在 - object 的元类是 type,但 A 的元类是 M_A。由于M_A 不是type 的子类,python 不知道要为A 使用哪个元类并抛出错误。


要解决此问题,请将 M_A 的父类更改为 type

class M_A(type): pass
class A(object, metaclass = M_A): pass

# no errors thrown

【讨论】:

以上是关于为啥具有对象基础的元类会引发元类冲突?的主要内容,如果未能解决你的问题,请参考以下文章

TypeError:元类冲突:派生类的元类

TypeError:元类冲突:派生类的元类必须是其所有基类的元类的(非严格)子类

TypeError:python中的元类冲突

Python 元类冲突

为啥一个类具有它的元类的属性?

unittest 模拟和多重继承:TypeError:元类冲突