一文详解Python中的super 函数

作者:华为云开发者联盟??????? 时间:2022-02-26 03:18:35 

实战场景

经常有朋友问,学 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. 如果到最后都没有找到,程序报错。

来源:https://blog.51cto.com/u_15214399/5652499

标签:Python,super,函数
0
投稿

猜你喜欢

  • php简单生成一组与多组随机字符串的方法

    2023-10-04 02:10:09
  • TensorFlow2.1.0安装过程中setuptools、wrapt等相关错误指南

    2023-07-30 10:28:08
  • Python测试网络连通性示例【基于ping】

    2023-09-16 13:48:38
  • Pandas中如何对DataFrame列名进行重命名

    2021-06-14 23:46:38
  • Python Pygame实战之塔防游戏的实现

    2021-12-15 08:57:22
  • mysql 8.0.12 安装配置图文教程

    2024-01-13 20:12:04
  • 关于python处理大型json文件的方法

    2023-09-24 12:47:47
  • Python强大的自省机制详解

    2021-06-07 02:07:57
  • Python安装.whl文件流程以及问题解决方法

    2022-10-24 15:15:23
  • Python的函数嵌套的使用方法

    2022-03-23 10:28:54
  • django与小程序实现登录验证功能的示例代码

    2023-08-04 01:06:58
  • Go错误处理之panic函数和recover函数使用及捕获异常方法

    2024-02-13 02:16:12
  • lodash内部方法getData和setData实例解析

    2024-04-19 09:43:12
  • 详解numpy.ndarray.reshape()函数的参数问题

    2022-02-06 20:22:57
  • Django框架 信号调度原理解析

    2022-05-14 20:04:46
  • jupyter notebook内核配置的图文教程

    2023-11-22 03:56:56
  • django框架中ajax的使用及避开CSRF 验证的方式详解

    2023-05-11 02:10:41
  • 为MySQL创建高性能索引

    2024-01-19 09:22:32
  • python实现微信跳一跳辅助工具步骤详解

    2023-08-02 11:11:40
  • MySQL数据库改名的详细方法教程

    2024-01-18 11:46:27
  • asp之家 网络编程 m.aspxhome.com