Python中的super函数,你熟吗?
摘要:经常有朋友问,学 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 funA(self):
print("执行 A ,输出橡皮擦")
class B(A):
def funB(self):
# 注意 super() 函数的用法
super().funA()
print("执行 B ,输出铅笔")
b = B()
b.funB()
此时输出的结果是 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函数,你熟吗?的更多相关文章
- 认识python中的super函数
需求分析 在类继承中,存在这么一种情况: class Human(object): def Move(self): print("我会走路...") class Man(Human ...
- python中的super( test, self).__init__()
python中的super( test, self).__init__() 对继承自父类的属性进行初始化 首先找到test的父类(比如是类A),然后把类test的对象self转换为类A的对象,然后“被 ...
- python中的super是什么?
技术背景 python中的super,名为超类,可以简单的理解为执行父类的__init__函数.由于在python中不论是一对一的继承,还是一子类继承多个父类,都会涉及到执行的先后顺序的问题.那么本文 ...
- python中的super()是什么?
技术场景:python中的super,名为超类,可以简单的理解为执行父类的__init__函数.由于在python中不论是一对一的继承,还是一子类继承多个父类,都会涉及到执行的先后顺序的问题.那么本文 ...
- python --- Python中的callable 函数
python --- Python中的callable 函数 转自: http://archive.cnblogs.com/a/1798319/ Python中的callable 函数 callabl ...
- python中使用zip函数出现<zip object at 0x02A9E418>
在Python中使用zip函数,出现<zip object at 0x02A9E418>错误的原因是,你是用的是python2点多的版本,python3.0对python做了改动 zip方 ...
- [转载]python中multiprocessing.pool函数介绍
原文地址:http://blog.sina.com.cn/s/blog_5fa432b40101kwpi.html 作者:龙峰 摘自:http://hi.baidu.com/xjtukanif/blo ...
- Python 中的isinstance函数
解释: Python 中的isinstance函数,isinstance是Python中的一个内建函数 语法: isinstance(object, classinfo) 如果参数object是cla ...
- Python中的map()函数和reduce()函数的用法
Python中的map()函数和reduce()函数的用法 这篇文章主要介绍了Python中的map()函数和reduce()函数的用法,代码基于Python2.x版本,需要的朋友可以参考下 Py ...
随机推荐
- docker实时查看日志
docker logs -f --tail=10 fo-order -f : 查看实时日志 --tail=10 : 查看最后的10条日志. fo-order: 容器名称
- STC8H开发(十三): I2C驱动DS3231高精度实时时钟芯片
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- 自己写雪花算法IdWorker
package com.aiyusheng.shopping.util; import java.lang.management.ManagementFactory; import java.net. ...
- Java中修饰符的分类及用法
访问权限修饰符: public 修饰class,方法,变量: 所修饰类的名字必须与文件名相同,文件中最多能有一个pulic修饰的类. private class不可用,方法,变量可以用: 只限于本类成 ...
- 大数据--Hive的安装以及三种交互方式
1.3 Hive的安装(前提是:mysql和hadoop必须已经成功启动了) 在之前博客中我有记录安装JDK和Hadoop和Mysql的过程,如果还没有安装,请先进行安装配置好,对应的随笔我也提供了百 ...
- 【PostgreSQL 15】PostgreSQL 15对UNIQUE和NULL的改进
用一句话来总结这种改进就是: 支持唯一性约束和索引将null值视为相同的值.之前是将null值索引成不同的值,现在可以通过使用unique nulls not distinct创建约束,将null值视 ...
- CF222C Reducing Fractions
题目大意: 给出两个集合,第一个集合数的乘积是分子,第二个集合的数的乘积是分母,要求够造一个同样的集合,但是得到的分数是最简分数. 分析: 寻找思路并不复杂,对两个集合的每个数进行质因数分解,然后统计 ...
- 从零开始Blazor Server(3)--添加cookie授权
认证方式简述 Blazor Server微软官方还是推荐直接使用Cookie授权,因为本来Blazor Server就是前后端不分离的.不存在Cookie跨域等一系列问题. 只要不是使用SSO之类的统 ...
- 从零开始Blazor Server(7)--使用Furion权限验证
序 上面两篇我们讲了怎么用OnNavigateAsync来验证权限,又写了怎么用策略来验证权限. 其实我们既然集成了Fution,就可以用Furion带的方式来验证. 创建AdminHandler 我 ...
- PerfView专题 (第一篇):如何寻找热点函数
一:背景 准备开个系列来聊一下 PerfView 这款工具,熟悉我的朋友都知道我喜欢用 WinDbg,这东西虽然很牛,但也不是万能的,也有一些场景他解决不了或者很难解决,这时候借助一些其他的工具来辅助 ...