metaclass冲突,多重继承和实例作为父类

4 投票
1 回答
2917 浏览
提问于 2025-04-17 02:40

我最近在研究Python,遇到了一些问题想请教一下。给定一个类Foo,我尝试了几种从它继承的方式:

  1. class A(Foo) — 这个方法可以正常工作,没什么意外的。
  2. class B(Foo()) — 这个也能工作,只要Foo有一个合适的__new__方法(我提供了这个方法)。
  3. class C(Foo(), Foo) — 这个也能工作,条件和B一样。
  4. class D(Foo, Foo()) — 这个就出错了,出现了著名的元类错误:

    错误追踪(最近的调用在最前面):
        文件 "test.py",第59行,
            类 D(Foo, Foo()):
    类型错误:元类冲突:派生类的元类必须是所有基类元类的(非严格)子类。

到底是什么导致了这个冲突呢?当我从(Foo(), Foo)(先实例化,再类)继承时是可以的,但当我从(Foo, Foo())(先类,再实例化)继承时就不行了。

1 个回答

5

当你“从一个实例继承”时,其实是在用一种奇怪的方式使用元类。通常,类对象是 type 的实例。在上面提到的 B 类中,它是从一个 Foo 的实例继承的。如果你用 Foo 作为元类来定义一个类,然后从这个类继承,结果就是这样。

我猜测这里发生的事情是,Python 正在反向处理基类的顺序。

C 类之所以能工作,是因为第一个被处理的父类是 Foo,而它的类是 type。这意味着 D 的元类必须是 type 或者它的某个子类。接着处理 Foo(),它的类是 Foo,而 Footype 的子类,所以一切正常。

D 类失败的原因是,第一个被处理的父类是 Foo(),这就要求 D 的元类必须是 Foo(或它的子类)。然后 Foo 被处理,它的类 type 不是 Foo 的子类。

这只是我的猜测,但你可以查查 Python 的元类文档,看看当你从两个不同元类的类中多重继承时,是否需要将它们按特定顺序排列,前提是这些元类之间有子类关系。

撰写回答