为什么具有对象基的元类会引发元类冲突?
Why does metaclass with object base raise metaclass conflict?
为什么在下面的代码中 metaclass 与对象基引发 metaclass 冲突异常?
"metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases"
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 的基 class 是 object,而任何 class 都是 [=22 的 subclass =]对象。这个错误太奇怪了。
我怎么了?
让我们仔细看看这个错误信息:
metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
这有点让人费解,让我们来看看是什么:
- "derived class"是
A
.
- "metaclass of a derived class"
A
是M_A
.
A
的基数 class 是 object
,因此 "the metaclasses of all its bases" 是 type
- 因为 type
是 object
的 metaclass.
这就是问题所在 - object
的元class 是 type
,但 A
的元class 是 M_A
.由于 M_A
不是 type
的子 class,python 不知道 A
使用哪个元 class 并抛出一个错误。
要解决此问题,请将 M_A
的父级 class 更改为 type
:
class M_A(type): pass
class A(object, metaclass = M_A): pass
# no errors thrown
为什么在下面的代码中 metaclass 与对象基引发 metaclass 冲突异常?
"metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases"
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 的基 class 是 object,而任何 class 都是 [=22 的 subclass =]对象。这个错误太奇怪了。 我怎么了?
让我们仔细看看这个错误信息:
metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
这有点让人费解,让我们来看看是什么:
- "derived class"是
A
. - "metaclass of a derived class"
A
是M_A
. A
的基数 class 是object
,因此 "the metaclasses of all its bases" 是type
- 因为type
是object
的 metaclass.
这就是问题所在 - object
的元class 是 type
,但 A
的元class 是 M_A
.由于 M_A
不是 type
的子 class,python 不知道 A
使用哪个元 class 并抛出一个错误。
要解决此问题,请将 M_A
的父级 class 更改为 type
:
class M_A(type): pass
class A(object, metaclass = M_A): pass
# no errors thrown