您能帮我理解这两种情况之间的区别吗?
class B1:
def f(self):
super().temp()
class B2:
def temp(self):
print("B2")
class A(B1, B2):
pass
A().f()
它打印“B2”
。
如果我们切换 B1
和 B2
:
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/