原文地址:   https://www.jianshu.com/p/de7d38c84443

---------------------------------------------------------------------------------------

python之理解super

super(type[, object-or-type])
  • type 类。
  • object-or-type 类,一般是 self。
 

1、super

在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过super()来实现,比如:


class Animal(object):
def __init__(self, name):
self.name = name def greet(self):
print('the animal name is %s' % self.name) class Dog(Animal):
def greet(self):
super(Dog, self).greet()
print('wangwang') dog = Dog('huang')
dog.greet()

结果:

the animal name is huang
wangwang

上面Animal是父类,Dog是子类,我们现在Dog类重定义了greet方法,为了能同时实现父类的功能,有利用super调用了父类的greet方法。

 


super一个常见的用法就是在子类中调用父类的初始化方法了,如:

class Base(object):
def __init__(self, a, b):
self.a = a
self.b = b class Inherit(Base):
def __init__(self, a, b, c):
# super(Inherit, self).__init__(a, b)
super().__init__(a, b) # py3支持的写法
self.c = c
print(self.a)
print(self.b)
print(self.c) test = Inherit('daocoder', 'mudai', 'dao')

结果:

daocoder
mudai
dao
 
 


2、深入理解super

上面基本是一般的用法和理解:获取父类,然后调用父类的方法。其实在上面的例子中,super获取的类恰好是父类而已,但在其它情况下就不一样了,super实质上和父类没有关联

class Base(object):
def __init__(self):
print('enter base')
print('leave base') class A(Base):
def __init__(self):
print('enter A')
super(A, self).__init__()
print('leave A') class B(Base):
def __init__(self):
print('enter B')
super(B, self).__init__()
print('leave B') class C(A, B):
def __init__(self):
print('enter C')
super(C, self).__init__()
print('leave C') c = C()

结果为:

enter C
enter A
enter B
enter base
leave base
leave B
leave A
leave C

Base是父类,A,B继承自Base,C继承自A,B。

如果按照之前的super代表是“调用父类的方法”,那么很可能会疑惑enter A的下一句不是enter Base而是enter B。(新式类是广度优先,旧式类是深度优先)。原因是super和父类没有实质性的关联。下面说明super是怎么运作的。
 
 
 
 
 
 
 
 

3、MRO列表

MRO(method resolution order),事实上,对于你定义的每个类,python都会计算出一个方法解析顺序,它代表了类继承的顺序。我们可以利用下面的方式获得某个类的MRO列表。

同样上面的代码。

print(C.mro())
print(C.__mro__)
print(c.__class__.mro())

结果为:

[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>)
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]
那么这个MRO列表的顺序是怎么定的呢,它是通过一个C3线性化算法来实现的,这里不讨论这个算法,简单来说,一个MRO列表就是合并所有父类的列表,并遵循下面几点:
  • 子类永远在父类的前面。
  • 如果有多个父类,会根据它们在列表中的顺序去检查。
  • 如果对下一个类存在两种不同的合法选择,那么选择第一个父类。
 
 
 
 
 

4、super原理

super的工作原理如下:

def super(cls, inst):
mro = inst.__class__.mro()
return mro[mro.index(cls) + 1]

cls代表类,inst代表实例,可以看出上面的代码做了两件事:

  • 获取inst的MRO列表。
  • 查找cls在MRO的index,并返回它的下一个类,即mro[index + 1]

当你使用super(cls, inst)时,python会在inst的MRO列表上搜索下cls的下一个类。

现在再回答前面的例子:

super(C, self).__init__()

这里的self是C的实例,self.class.mro()的结果是:

[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]

可以看到C的下一个类是A,于是,跳到了A的init,这时会打印enter A,并且执行下面一行代码:

super(A, self).__init__()
 注意这里的self也是当前C的实例,MRO列表和之前是一样的。搜索A在MRO中下的一个类,发现是B,于是又跳到了B的init,这时会打印enter B,而不是enter Base。
 

上面整个过程还是比较清晰的,关键在于理解super的工作方式,而不是想当然的理解为super调用父类的方法

总结:

  • super和父类没有实质性的关联。
  • super(cls, inst)获得的是cls在inst的MRO列表中下一个类。

原文出处:Python: 你不知道的 super

 
 
 
 
 
 
 
 
----------------------------------------------------------------------
 

作者:道无虚
链接:https://www.jianshu.com/p/de7d38c84443
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


【转载】 python之理解super及MRO列表的更多相关文章

  1. super之mro列表牵引出c3算法

    目录 一:super的使用 二:super之mro列表牵引出c3算法 三:mro列表总结使用 一:super的使用 class Person(object): def __init__(self, n ...

  2. 子类中执行父类的方法(引出super()与mro列表)

    1. 我们先想一下在python中如果子类方法中想执行父类的方法,有什么方式?大概有三种: Parent.__init__(self, name) # 通过父类的名字,指定调用父类的方法 super( ...

  3. [转载]Python: 你不知道的 super

    原文出处: geekvi super() 的入门使用 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用  ...

  4. 认识python中的super函数

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

  5. Python大神必须掌握的技能:多继承、super和MRO算法

    本文主要以Python3.x为例讲解Python多继承.super以及MRO算法. 1. Python中的继承 任何面向对象编程语言都会支持继承,Python也不例外.但Python语言却是少数几个支 ...

  6. Python进阶-继承中的MRO与super

    Python进阶-继承中的MRO与super 写在前面 如非特别说明,下文均基于Python3 摘要 本文讲述Python继承关系中如何通过super()调用"父类"方法,supe ...

  7. Python面向对象中super用法与MRO机制

    1. 引言 最近在研究django rest_framework的源码,老是遇到super,搞得一团蒙,多番查看各路大神博客,总算明白了一点,今天做一点总结. 2. 为什么要用super 1)让代码维 ...

  8. Python的多继承问题-MRO和C3算法

    大部分内容转载自C3 线性化算法与 MRO 理解Python中的多继承 Python 中的方法解析顺序(Method Resolution Order, MRO)定义了多继承存在时 Python 解释 ...

  9. 继承及属性查找+super()和mro()+多态

    继承及属性查找+super()和mro()+多态 一. ★继承 1. 什么是继承? 继承就是新建类的一种方式,新建的类我们称为子类或者叫派生类,被继承的类我们称为父类或者基类 子类可以使用父类中的属性 ...

  10. Python类中super()和__init__()的关系

    Python类中super()和__init__()的关系 1.单继承时super()和__init__()实现的功能是类似的 class Base(object): def __init__(sel ...

随机推荐

  1. WIN8 WIN10 WIN11离线安装 .NET 3.5

    WIN8 WIN10 WIN11离线安装 .NET 3.5 以WIN10为例: 1.双击WIN10 ISO 镜像,看挂载的是哪个盘符.我这边是E:. 2.使用 WIN + X 快捷键,打开 Windo ...

  2. HP惠普战66电源黄灯闪烁无法充电

    HP惠普战66电源黄灯闪烁无法充电 TYPE-C PD 无法充电. 解决办法:关机状态下,拔除外部设备,长按电源键30秒以释放主板静电,再插电源线可以开机.

  3. axios 下载文件流

    axios 下载文件流 背景:在处理文件下载时,服务端存在校验,需要在请求头里添加token 这时直接使用 a 标签就不能满足需求.接下来我们直接通过 axios 请求,在请求头里设置 token 请 ...

  4. xshell和xftp远程SSH密钥连接腾讯云服务器

    1.在腾讯云中创建密钥,关机,绑定. 2.xshell和xftp导入密钥,填写的用户名和密码验证是 腾讯云的主机的root和密码(关键,而不是创建密钥的用户名和密码),该密码可以重置.

  5. Java基础:throw和throws的详解

    总结来说,throw是用来抛出一个具体的异常实例,而throws是用来声明方法可能会抛出哪些类型的异常,是对调用者的一种通知和要求. 1. throw 作用: throw关键字用于在方法体内实际抛出一 ...

  6. W801单片机入门开发环境设置

    W801单片机入门开发环境设置 开发软件下载 烧录工具和SDK 在 WinnerMicro的网站 https://www.winnermicro.com/html/1/156/158/558.html ...

  7. Linux驱动中的等待队列与休眠

    Linux驱动中的等待队列与休眠 原文:https://blog.csdn.net/mengluoxixiang/article/details/46239523?spm=1001.2014.3001 ...

  8. 中间件-Nginx

    一.nginx反向代理 输入 http://xxx.com/plat/login 跳转: http://localhost:8383/plat/login 将某个指定的域名代理到指定的服务 http: ...

  9. 使用64位Office2016处理万级数据的过程

    先放下载和安装教程https://mp.weixin.qq.com/s/5ym9950_NZROlN0s2ZmLTg 由于同事电脑在使用Mysql for Excel插件处理十万级数据,如下图: 爆出 ...

  10. Centos7搭建Minio环境(配置开机自启)

    Minio 添加环境变量 # 设置控制台账号 最少3位 export MINIO_ACCESS_KEY=admin # 设置密码 最少8位 export MINIO_SECRET_KEY=123456 ...