gpt4 book ai didi

python - 一个关于C3的例子

转载 作者:行者123 更新时间:2023-11-28 18:03:48 25 4
gpt4 key购买 nike

我从github上得到了以下关于MRO和C3的代码,我不太明白最后三行,super().foo(), super(B,self).foo( )和python3.x中的super(C,self).foo(),代码如下:

class A(object):

def foo(self):
print('foo of A')

class B(A):
pass

class C(A):

def foo(self):
print('foo fo C')

class D(B, C):
pass

class E(D):

def foo(self):
print('foo in E')
super().foo()
super(B, self).foo()
super(C, self).foo()

if __name__ == '__main__':
d = D()
d.foo()
e = E()
e.foo()

预期和实际结果如下:

foo fo C
foo in E
foo fo C
foo fo C
foo of A

最佳答案

首先,表格super()在 Python 3 中实际上与 super(<CurrentClass>, self) 相同,其中 Python 编译器 provides enough information for super() to determine what the correct class to use is .所以在 E.foo() , super().foo()可以读作 super(E, self).foo() .

要了解发生了什么,您需要查看 class.__mro__ attribute :

This attribute is a tuple of classes that are considered when looking for base classes during method resolution.

正是这个元组向您展示了对于任何给定的类层次结构,C3 方法解析顺序 是什么。为您的类(class)E ,那个顺序是:

>>> E.__mro__
(<class '__main__.E'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
>>> for cls in E.__mro__: # print out just the names, for easier readability.
... print(cls.__name__)
...
E
D
B
C
A
object

super()对象基于有序的类序列中的所有内容。呼唤

super(SomeClass, self).foo()

导致以下一系列步骤:

  • super()对象检索 self.__mro__元组。
  • super()找到 SomeClass 的索引该元组中的类。
  • 访问 foo super() 上的属性对象触发搜索具有 foo 的类MRO 上的属性,SomeClass 之后的下一个索引开始索引.
  • 如果以这种方式找到的属性是 descriptor object将以这种方式找到的属性绑定(bind)到 self .函数是描述符,绑定(bind)产生绑定(bind)方法,Python 就是这样传入 self 的。调用方法时的引用。

表示为简化的 Python 代码,忽略了 super() 的边缘情况和其他用途,看起来像:

class Super:
def __init__(self, type_, obj_or_type):
self.mro = obj_or_type.__mro__
self.idx = self.mro.index(type_) + 1
self.obj_or_type = obj_or_type
def __getattr__(self, name):
for cls in self.mro[self.idx:]:
attrs = vars(cls)
if name in attrs:
result = attrs[name]
if hasattr(result, '__get__'):
result = result.__get__(obj_or_type, type(self.obj_or_type))
return result
raise AttributeError(name)

结合这两条信息,您可以看到调用 e.foo() 时会发生什么:

  • print('foo in E')被执行,导致 foo in E
  • super().foo()被执行,实际上与 super(E, self).foo() 相同.
    • 搜索 MRO,从 过去 的下一个索引开始 E ,所以在 D (没有 foo 属性),继续 B (没有 foo 属性),然后是 C (找到属性)。 C.foo返回,绑定(bind)到 self .
    • C.foo(self)被调用,导致 foo fo C
  • super(B, self).foo()被执行。
    • 搜索 MRO,从 过去 的下一个索引开始 B ,所以在 C (找到属性)。 C.foo返回,绑定(bind)到 self .
    • C.foo(self)被调用,导致 foo fo C
  • super(C, self).foo()被执行。
    • 搜索 MRO,从 过去 的下一个索引开始 C ,所以在 A (找到属性)。 A.foo返回,绑定(bind)到 self .
    • A.foo(self)被调用,导致 A 的 foo

关于python - 一个关于C3的例子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54756219/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com