本文分享自华为云社区《Python 中的 super 函数怎么学,怎么解?》,作者:梦想橡皮擦。

实战场景

常常有朋友问,学 Python 面向目标时,翻阅别人代码,会发现一个 super() 函数,那这个函数的效果究竟是什么?

super() 函数的用处如下,在子类中调用父类的办法,多用于类的承继联系。

其语法格式如下所示:

super(type[, object-or-type])

参数阐明如下:

  • type:类,可选参数
  • object-or-type:目标或类,一般为 self,也是可选参数。

回来值是代理目标。

能够直接查询官方帮助手册:

help(super)

输出信息如下所示:

Help on class super in module builtins:
class super(object)
 |  super() -> same as super(__class__, <first argument>)
 |  super(type) -> unbound super object
 |  super(type, obj) -> bound super object; requires isinstance(obj, type)
 |  super(type, type2) -> bound super object; requires issubclass(type2, type)
 |  Typical use to call a cooperative superclass method:
 |  class C(B):
 |      def meth(self, arg):
 |          super().meth(arg)
 |  This works for class methods too:
 |  class C(B):
 |      @classmethod
 |      def cmeth(cls, arg):
 |          super().cmeth(arg)

对输出成果进行分析之后,能够得到如下结论:

  • super 类是一个承继自 object 的类,super() 函数便是对该类的实例化
  • 调用 super() 实例化之后,回来一个 super 目标;
  • super() 参数有四种调配,具体看上述输出;

实战编码

单承继运用

直接看一下单承继相关代码,其间运用类名去调用父类办法。

class A:
 def funA(self):
 print("履行 A ,输出橡皮擦")
class B(A):
 def funB(self):
 # self 表明 B 类的实例
 A.funA(self)
 print("履行 B ,输出铅笔")
b = B()
b.funB()

上述代码在 B 类中增加了 funB 函数,而且去调用 A 类中的 funA 函数,此刻输出的内容如下所示:

履行 A ,输出橡皮擦
履行 B ,输出铅笔

假如将上述代码修正为 super() 函数调用父类办法,能够运用下述代码:

class A:
 def funA(self):
 print("履行 A ,输出橡皮擦")
class B(A):
 def funB(self):
 # 注意 super() 函数的用法
 super().funA()
 print("履行 B ,输出铅笔")
b = B()
b.funB()

上述代码与之前的运行成果一致,在单承继的层级结构中,super 能够直接引用父类,即在子类中不需要运用父类名调用父类办法,而运用 代理目标(super 目标) 去调用,这样的好处便是当父类名改动或承继联系发生改动时,咱们不需要对调用进行反复修正。

接下来看一下多承继情况下,super() 函数的实战场景。

class A:
 def run(self):
 print('AAA')
class B:
 def run(self):
 print('BBB')
class C:
 def run(self):
 print('CCC')
class D(A, B, C):
 def run(self):
 super().run()
d = D()
d.run()

此刻输出的成果是 AAA,能够看到 super 匹配到的数据是 A 类中的 run 函数,也便是最左边类中的办法,下面修正一下各类中 run 函数的名称,使其存在差异。

class A:
 def run1(self):
 print('AAA')
class B:
 def run2(self):
 print('BBB')
class C:
 def run3(self):
 print('CCC')
class D(A, B, C):
 def run(self):
 # 调用 B 中 run2
 super().run2()
d = D()
d.run()

当一个类承继多个类时,假如第一个父类中没有提供该办法,当时类实例就会通过 __mro__ 特点进行向上查找,假如到 object 类都没有检索到该办法,就会引发 AttributeError 反常。

根据上述逻辑,咱们能够扩展一下,运用 super() 函数中的参数。

class A:
 def run(self):
 print('AAA')
class B:
 def run(self):
 print('BBB')
class C:
 def run(self):
 print('CCC')
class D(A, B, C):
 def run(self):
 # 调用 C 中 run
 super(B, self).run()
d = D()
d.run()

此刻输出的成果是 CCC,该成果输出表明了运用 super 函数之后,能够运用 super(类,self) 指定以哪个类为起点检索父类中的办法,上述代码设置的 B,就表明从 B 开始检索,后续找到了 C 类,其间包含 run() 办法,所以输出 CCC。

__mro__ 特点的阐明。

MRO 是 method resolution order,即办法解析次序,其本质是承继父类办法时的次序表。在 Python 中能够运用内置特点 __mro__ 检查办法的查找次序,例如下述代码,重点检查输出部分内容。

class A:
 def run(self):
 print('AAA')
class B:
 def run(self):
 print('BBB')
class C:
 def run(self):
 print('CCC')
class D(A, B, C):
 def run(self):
 # 调用 C 中 run
 super(B, self).run()
print(D.__mro__)

输出的成果如下所示:

(<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>)

你能够修正一下承继次序,然后得到不同的输出成果。

(<class '__main__.D'>, <class '__main__.A'>, <class '__main__.C'>, <class '__main__.B'>, <class 'object'>)

在查找办法的时分,是依照 __mro__ 的输出成果从左到右进行次序查找的,逻辑如下:

A. 找到办法,停止检索;

B. 没有找到,持续检索下一类;

C. 假如到最后都没有找到,程序报错。

点击关注,第一时间了解华为云新鲜技能~