前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python的super函数直观理解

Python的super函数直观理解

作者头像
marsggbo
发布2021-03-15 21:35:03
7230
发布2021-03-15 21:35:03
举报
文章被收录于专栏:AutoML(自动机器学习)

super相关的介绍文章看了无数遍,每次看得都云里雾里的,没过多久就忘了,只模糊知道跟MRO有关,但是稍微一复杂就不知道怎么回事了,本篇文章主要记录我对super的理解,尽量以简单易懂的方式介绍,如果你看完这篇文章还是没懂。。。那么很抱歉,我尽力了hhhh

粗暴简单的理解

super的作用就是执父类的方法,虽然这句话不完全对,但是也差不多是那么个意思了。

比如以单继承为例

代码语言:javascript
复制
class A:
    def p(self):
        print('A')
class B(A):
    def p(self):
        super().p()
B().p()

>>> A

可以看到B().p()其实就是执行的A.p

万能模板解题技巧

前面介绍的是最简单的情况,那万一复杂一点,比如多继承的情况呢?这种情况我们只要知道 MRO 序列,无论super怎么变化都不怕了,记住公式就完事了。MRO 序列简单理解就是记录了各个类继承的先后顺序,看下面的例子就明白了

MRO 的介绍可以看这篇文章: https://python3-cookbook.readthedocs.io/zh_CN/latest/c08/p07_calling_method_on_parent_class.html

我们看下面的例子

代码语言:javascript
复制
class A:
    def p(self):
        print('A')
class B():
    def p(self):
        print('B')
class C(A,B):
    def p(self):
        print('C')
class D(C):
    def p(self):
        print('D')
a = A()
b = B()
c = C()
d = D()

四个类的MRO (可以通过查看__mro__属性获得,例如A.__mro__)) 分别是:

  • A: (A, object)
  • B: (B, object)
  • C: (C, A, B, object)
  • D: (D, C, A, B, object)

什么意思呢,我们以A类为例,它的MRO顺序是他自己和object,很好理解,因为python里一切都是对象,所以你可以看到四个类的终点都是object。那C类的 MRO 也好理解,第一个顺序永远是寄几,然后按照代码顺序依次是 A,B,最后是object

相信看到这你应该知道MRO是什么意思了吧,那super是怎么用的呢?

super本身其实就是一个类,super()其实就是这个类的实例化对象,它需要接收两个参数 super(class, obj),它返回的是obj的MRO中class类的父类(可能有点绕,待会看后面的栗子就好懂了):

  • class:就是类,这里你可以是A,B,C或者D
  • obj:就是一个具体的实例对象,即a,b,c,d。我们经常在类的__init__函数里看到super的身影,而且一般都是写成这个样子的super(className, self).__init__()self其实就是某个实例化的对象。

举几个栗子

看到这里如果还是没明白,咱们就多看几个例子就完事了,建议你可以打开ipython输入如下示例,可以更加直观感受super

栗子1

首先我们看看下面的命令是什么意思呢?

代码语言:javascript
复制
super(C, d).p()

前面我们说过super的作用是 返回的是obj的MRO中class类的父类,在这里就表示返回的是d的MRO中C类的父类

  1. 返回的是d的MRO:(D, C, A, B, object)
  2. C类的父类:A

那么super(C, d)就等价于A,那么super(C, d).p()会输出A

栗子2

下面代码结果是什么呢?

代码语言:javascript
复制
super(A, c).p()

返回的是c的MRO中A类的父类

  1. 返回的是c的MRO:(C, A, B, object)
  2. C类的父类:B

所以最后的输出是B

最后几个栗子

注意:有的类里面没有super()

代码语言:javascript
复制
class A:
    def p(self):
        print('A')
class B(A):
    def p(self):
		super().p()
        print('B')
class C(B):
    def p(self):
        print('C')
class D(C):
    def p(self):
        print('D')

d = D()
d.p()

这个很简单,最后只会输出D

那如果D类改成如下样子呢?

代码语言:javascript
复制
class D(C):
    def p(self):
		super().p()
        print('D')

很简单,我们首先写出D的MRO为 (D,C,B,A,object),缺省状态下,super()就表示前一个父类,这里就是C类,那么super().p()就会调用Cp函数,但是C.p里没有调用super,所以就与A,B类无关了,那么最终的输出就是C,D

我们再看看最复杂的继承情况

代码语言:javascript
复制
class A:
    def p(self):
        print('A')
class B(A):
    def p(self):
        super().p()
        print('B')
class C(B):
    def p(self):
        super().p()
        print('C')
class D(C):
    def p(self):
        super().p()
        print('D')
d = D()
d.p()

这里建议你自己在纸上画一下

所以最终结果是 A B C D

总结

对于无论有多少个super(class, obj),我们首先需要知道obj的MRO是什么,然后找到class的前一个class是什么就好了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-03-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 粗暴简单的理解
  • 万能模板解题技巧
  • 举几个栗子
    • 栗子1
      • 栗子2
        • 最后几个栗子
        • 总结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档