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())

结果为:

[, , , , ]

(, , , , )

[, , , , ]

那么这个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()的结果是;

[, , , , ]

可以看到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 mro_python之理解super及MRO列表相关推荐

  1. python中类怎么理解_Python中的列表理解

    python中类怎么理解 In order to create a list, a most obvious and remembered solution is to use a for-loop. ...

  2. python 多继承与super使用详解_继承中的MRO与super详解

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

  3. python的类的super()

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

  4. python类的继承super方法_Python类的继承super相关原理解析

    看了网上许多关于super.mro.C3的介绍感觉没有一份很容易初学者理解的文档,直接看C3算法的话,比较难理解,也没必要,如果掌握一套规律的话,会轻松许多.我将网上这些博主的文章进行一个梳理总结,最 ...

  5. Python进阶:理解元类创建类ABCMeta

    Python进阶:Python进阶:理解元类创建类ABCMeta 一.理解元类(Meta class) 1.1 元类直观理解 1.2 Python官方文档给出的元类描述 二.理解抽象基类(ABC, A ...

  6. Python(迭代、三元表达式、列表生成、生成器、迭代器)

    迭代 什么是迭代1 重复2 下次重复一定是基于上一次的结果而来 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration). 在 ...

  7. Python高级特性(切片,迭代,列表生成式,生成器,迭代器)

    掌握了Python的数据类型.语句和函数,基本上就可以编写出很多有用的程序了. 比如构造一个1, 3, 5, 7, ..., 99的列表,可以通过循环实现: L = [] n = 1 while n ...

  8. python class 是否存在某个变量_一文抵十课,考验你的Python变量是否理解透彻了

    变量是编程的基础概念,Python 的变量也看似很简单,但是如果理解不当,生搬硬套,可能会遇到一些麻烦. 下面用 10 个代码示例展示 Python 的 变量 本质. 快来看看你对 Python 的变 ...

  9. python args kwargs 理解_*args和**kwargs在python中的作用

    我发现PYTHON新手在理解*args和**kwargs这两个魔法变量的时候有些困难.他们到底是什么呢? 首先,我先告诉大家一件事情,完整地写*args和**kwargs是不必要的,我们可以只写*和* ...

  10. python基础入门(6)之列表

    目录 一.Python列表 一.列表基本知识 1)创建列表 2)列出表值 3)列表长度 4)列表项 - 数据类型 5)Python 集合(数组) 二.访问列表 1.正常索引 2)负索引 3)索引范围 ...

最新文章

  1. 把eclipse从英文调整为中文
  2. 解决“由于应用程序的配置不正确,应用程序未能启动,重新安装应用程序可能会纠正这个问题”...
  3. java session 是什么意思_Java:Session详解
  4. redis 分布式锁 看门狗_漫谈分布式锁之Redis实现
  5. vue 获取元素高度
  6. 腾讯一面总结-web前端-2018.4.11
  7. js调用php会提前加载,为什么js代码里调用了php变量运行就明显变慢了
  8. “聆听”升级,阿里云智能喜迎首席聆听官
  9. 彻底弄明白之数据结构中的排序七大算法-java实现
  10. [Linux学习]更改默认启动图形界面或命令行
  11. dnn305的一个bug
  12. 北斗导航 | 基于奇偶矢量法的RAIM之SSE探索(附奇偶矢量法源代码)
  13. mac m1 安装svn/subversion
  14. 摩拜开锁系统是用什么服务器,摩拜昨晨现“开锁难” 市民:系统需更稳定
  15. c语言编fft算法程序,FFT算法的C语言编程
  16. HTML5+CSS3 Pink老师课后作业——小米logo过渡切换的实现
  17. 最轻松mflac转flac、mp3方法
  18. 上传文件到云服务器一般用什么软件?
  19. 怎么把手机屏幕投射镜像到电脑上面?
  20. 合并两个有序表(C语言)

热门文章

  1. 2013级C++第2周(春)项目——结构体应用大体验
  2. 实现黑客帝国中的代码雨 快进来学(附源代码)
  3. 项目合同管理:合同分类、费用支付方式、违约责任承担方式、签订注意事项、合同索赔流程
  4. 前端开发实习面试题(Vue篇)
  5. Photoshop如何调整证件照背景色
  6. android x86触屏驱动下载,农步祥作品 - 使用台式机和触摸屏玩Android X86 [Soomal]
  7. 【张朝阳的物理课笔记】 1. 力,牛顿定律,飞船角速度
  8. am355x armlinux 移植openssh
  9. sklearn实现决策树
  10. html caption属性的值,如何设置caption属性