python - 多重继承中基类的顺序和 super() 的使用

标签 python python-3.x multiple-inheritance super

您能帮我理解这两种情况之间的区别吗?

class B1:
    def f(self):
        super().temp()

class B2:
    def temp(self):
        print("B2")

class A(B1, B2):
    pass

A().f()

它打印“B2”

如果我们切换 B1B2:

class A(B2, B1):
    pass

A().f()

我得到AttributeError:'super'对象没有属性'temp'

最佳答案

Python 使用名为 C3 linearization 的东西决定基类的顺序:“方法解析顺序”。非正式地说,这基本上有两个部分:

  • 路径必须层次结构决不能从类向下向下到达其父类(super class),即使是间接的。因此,不允许存在循环,并且 issubclass(X, Y) 和 issubclass(Y, Z) 意味着 issubclass(X, Z)

  • 当不受上述规则强制时,顺序按最高级类的步骤数排序(步骤数越少意味着链中的较早),然后然后的顺序类列表中的类(列表中较早的部分意味着链中较早的部分)。

这里的层次结构是:

    A
   / \
  /   \
B1     B2   # Possibly switched
  \   /
   \ /
  object

在第一种情况下,C3线性化后的顺序是

  super    super    super
A   →   B1   →   B2   →   object

我们可以通过以下方式找到:

A.mro()
#>>> [<class 'A'>, <class 'B1'>, <class 'B2'>, <class 'object'>]

因此 super() 调用将解析为:

class A(B1, B2):
    pass

class B1:
    def f(self):
        # super() proxies the next link in the chain,
        # which is B2. It implicitly passes self along.
        B2.temp(self)

class B2:
    def temp(self):
        print("B2")

因此调用A().f()尝试:

  • f 是否在实例上?不,所以
  • f 是否在第一节课 A 上?不,所以
  • f 是否在下一个类 B1 上?是的!

然后调用 B1.f 并调用 B2.temp(self),它会检查:

  • f 是否在类(class) B2 上?是的!

它被调用,打印B2

在第二种情况下,我们有

  super    super    super
A   →   B2   →   B1   →   object

所以解决了

因此 super() 调用将解析为:

class A(B2, B2):
    pass

class B2:
    def temp(self):
        print("B2")

class B1:
    def f(self):
        # super() proxies the next link in the chain,
        # which is B2. It implicitly passes self along.
        object.temp(self)
  • f 是否在实例上?不,所以
  • f 是否在第一节课 A 上?不,所以
  • f 是否在下一个类 B2 上?不,所以
  • f 是否在下一个类 B1 上?是的!

因此调用 B1.f 并调用 object.temp(self),它会检查:

  • f 是否在类 object 上?不,
  • 没有父类(super class),因此我们未能找到该属性。
  • 引发 AttributeError("{!r} 对象没有属性 {!r}".format(instance, attribute_name))

关于python - 多重继承中基类的顺序和 super() 的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26702486/

相关文章:

javascript - 从其他类继承原型(prototype)方法而不覆盖自己的原型(prototype)方法

c++ - 非虚拟析构子的双重继承(Y 形)

python - 函数返回字符串错误

python-3.x - 如何使用 StringField 验证 Flask 表单中的电话号码?定义最小/最大长度不能限制用户输入文本

javascript - Selenium Web 驱动程序访问 Jquery 中的 Javascript 全局变量

python-3.x - 如何检查列表理解中的 np.nan ?

python - 找出一个单词中的一半字母是否是元音

c++ - 在可变参数模板中使用声明

python - Turbogears2 与 MySQL 数据库不更新多线程中的表

python - 从 csv 读取并检查 IP 地址可达性