摘要:经常有朋友问,学 Python 面向对象时,翻阅别人代码,会发现一个 super() 函数,那这个函数的作用到底是什么?

本文分享自华为云社区《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. 如果到最后都没有找到,程序报错。

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

想了解Python中的super 函数么的更多相关文章

  1. Python中的super函数,你熟吗?

    摘要:经常有朋友问,学 Python 面向对象时,翻阅别人代码,会发现一个 super() 函数,那这个函数的作用到底是什么? 本文分享自华为云社区<Python中的super函数怎么学,怎么解 ...

  2. 认识python中的super函数

    需求分析 在类继承中,存在这么一种情况: class Human(object): def Move(self): print("我会走路...") class Man(Human ...

  3. python中使用zip函数出现<zip object at 0x02A9E418>

    在Python中使用zip函数,出现<zip object at 0x02A9E418>错误的原因是,你是用的是python2点多的版本,python3.0对python做了改动 zip方 ...

  4. Python中的map()函数和reduce()函数的用法

    Python中的map()函数和reduce()函数的用法 这篇文章主要介绍了Python中的map()函数和reduce()函数的用法,代码基于Python2.x版本,需要的朋友可以参考下   Py ...

  5. python中的生成器函数是如何工作的?

    以下内容基于python3.4 1. python中的普通函数是怎么运行的? 当一个python函数在执行时,它会在相应的python栈帧上运行,栈帧表示程序运行时函数调用栈中的某一帧.想要获得某个函 ...

  6. python中的super( test, self).__init__()

    python中的super( test, self).__init__() 对继承自父类的属性进行初始化 首先找到test的父类(比如是类A),然后把类test的对象self转换为类A的对象,然后“被 ...

  7. python中的map()函数

    MapReduce的设计灵感来自于函数式编程,这里不打算提MapReduce,就拿python中的map()函数来学习一下. 文档中的介绍在这里: map(function, iterable, .. ...

  8. 揭秘 Python 中的 enumerate() 函数

    原文:https://mp.weixin.qq.com/s/Jm7YiCA20RDSTrF4dHeykQ 如何以去写以及为什么你应该使用Python中的内置枚举函数来编写更干净更加Pythonic的循 ...

  9. Python3中的super()函数详解

    关于Python3中的super()函数 我们都知道,在Python3中子类在继承父类的时候,当子类中的方法与父类中的方法重名时,子类中的方法会覆盖父类中的方法, 那么,如果我们想实现同时调用父类和子 ...

  10. Python中的lambda函数介绍

    Lambda函数,即Lambda 表达式(lambda expression),是一个匿名函数(不存在函数名的函数),Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lam ...

随机推荐

  1. 初识FreeRTOS

    FreeRTOS是一个迷你的实时操作系统内核.作为一个轻量级的操作系统,功能包括:任务管理.时间管理.信号量.消息队列.内存管理.记录功能.软件定时器.协程等,可基本满足较小系统的需要.   一.Fr ...

  2. kafka和zookeeper安装

    一.Kafka简介 Kafka 被称为下一代分布式消息系统,是非营利性组织ASF(Apache Software Foundation,简称为ASF)基金会中的一个开源项目,比如HTTP Server ...

  3. JUC并发编程学习笔记(十五)JMM

    JMM 请你谈谈对Volatile的理解 Volatile是java虚拟机提供的轻量级的同步机制 1.保证可见性 2.不保证原子性 3.禁止指令重排 什么是JMM JVM->java虚拟机 JM ...

  4. 【发布】DDD 工程脚手架 + 一键安装分布式技术栈环境!

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 大家好,我是技术UP主小傅哥. 写了那么多案例工程,开发了那么多技术项目.那小傅哥做的这些案例 ...

  5. 请问您今天要来点 ODT 吗

    梗出处:请问您今天要来点兔子吗? 这篇文章主要记录一下自己学习 \(\text{ODT}\) 发生的种种. CF896C Willem, Chtholly and Seniorious \(\text ...

  6. Codeforces Global Round 13 A-D题题解

    写在前边 链接:Codeforces Global Round 13 \(A,B,C,D\) A. K-th Largest Value 链接:A题链接 题目大意: 有一个字串只由\(0.1\)组成, ...

  7. C#12中的Collection expressions(集合表达式语法糖)

    C#12中引入了新的语法糖来创建常见的集合.并且可以使用..来解构集合,将其内联到另一个集合中. 支持的类型 数组类型,例如 int[]. System.Span<T> 和 System. ...

  8. C语言一辆卡车撞人逃逸。现场三人目击事件,只记下车的一些特征。甲说:牌照的前两位数字是相同的;乙说:牌照的后两位数字是相同的;丙是位数学家说:四位的车号正好是一个整数的平方

    #include <stdio.h> #include <math.h> void main() { int a, b, c, d, n, h; double t; for ( ...

  9. 文心一言 VS 讯飞星火 VS chatgpt (142)-- 算法导论12.1 2题

    二.用go语言,二叉搜索树性质与最小堆性质(见 6.1 节)之间有什么不同?能使用最小堆性质在 O(n)时间内按序输出一棵有 n 个结点树的关键字吗?可以的话,请说明如何做,否则解释理由. 文心一言: ...

  10. 管易云与网易互客对接集成发货单查询2.0=>编辑订单

    管易云与网易互客对接集成发货单查询2.0=>编辑订单 对接源平台:管易云 管易云是金蝶旗下专注提供电商企业管理软件服务的子品牌,先后开发了C-ERP.EC-OMS.EC-WMS.E店管家.BBC ...