python 中的 super 函数怎么学,怎么解?-4008云顶国际网站
文章目录
⛳️ 实战场景
经常有朋友问,学 python 面向对象时,翻阅别人代码,会发现一个 super()
函数,那这个函数的作用到底是什么?
super()
函数的用途如下,在子类中调用父类的方法,多用于类的继承关系。
其语法格式如下所示:
super(type[, object-or-type])
- 1
参数说明如下:
type
:类,可选参数object-or-type
:对象或类,一般为 self,也是可选参数。
返回值是代理对象。
可以直接查询官方帮助手册:
help(super)
- 1
输出信息如下所示:
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)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
对输出结果进行分析之后,可以得到如下结论:
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()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
上述代码在 b 类中增加了 funb
函数,并且去调用 a 类中的 funa
函数,此时输出的内容如下所示:
执行 a ,输出橡皮擦
执行 b ,输出铅笔
- 1
- 2
如果将上述代码修改为 super()
函数调用父类方法,可以使用下述代码:
class a:
def funa(self):
print("执行 a ,输出橡皮擦")
class b(a):
def funb(self):
# 注意 super() 函数的用法
super().funa()
print("执行 b ,输出铅笔")
b = b()
b.funb()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
上述代码与之前的运行结果一致,在单继承的层级结构中,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()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
此时输出的结果是 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()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
当一个类继承多个类时,如果第一个父类中没有提供该方法,当前类实例就会通过 __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()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
此时输出的结果是 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__)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
输出的结果如下所示:
(<class '__main__.d'>, <class '__main__.a'>, <class '__main__.b'>, <class '__main__.c'>, <class 'object'>)
- 1
你可以修改一下继承顺序,然后得到不同的输出结果。
(<class '__main__.d'>, <class '__main__.a'>, <class '__main__.c'>, <class '__main__.b'>, <class 'object'>)
- 1
在搜索方法的时候,是按照 __mro__
的输出结果从左到右进行顺序查找的,逻辑如下:
a. 找到方法,停止检索;
b. 没有找到,继续检索下一类;
c. 如果到最后都没有找到,程序报错。
📢📢📢📢📢📢
💗 你正在阅读 【梦想橡皮擦】 的博客
👍 阅读完毕,可以点点小手赞一下
🌻 发现错误,直接评论区中指正吧
📆 橡皮擦的第 717 篇原创博客
从订购之日起,案例 5 年内保证更新
文章来源: dream.blog.csdn.net,作者:梦想橡皮擦,4008云顶国际集团的版权归原作者所有,如需转载,请联系作者。
原文链接:dream.blog.csdn.net/article/details/126279613
- 点赞
- 收藏
- 关注作者
评论(0)