为啥具有对象基础的元类会引发元类冲突?
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
。
“派生类的元类” A
是 M_A
。
A
的基类是 object
,因此 “所有基类的元类” 是 type
- 因为 type
是 object
的元类。
这就是问题所在 - 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
【讨论】:
以上是关于为啥具有对象基础的元类会引发元类冲突?的主要内容,如果未能解决你的问题,请参考以下文章