python mro_python之理解super及MRO列表
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列表相关推荐
- python中类怎么理解_Python中的列表理解
python中类怎么理解 In order to create a list, a most obvious and remembered solution is to use a for-loop. ...
- python 多继承与super使用详解_继承中的MRO与super详解
Python进阶-继承中的MRO与super 写在前面如非特别说明,下文均基于Python3 摘要 本文讲述Python继承关系中如何通过super()调用"父类"方法,super ...
- python的类的super()
super() 的入门使用 在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super 来实现,比如: ...
- python类的继承super方法_Python类的继承super相关原理解析
看了网上许多关于super.mro.C3的介绍感觉没有一份很容易初学者理解的文档,直接看C3算法的话,比较难理解,也没必要,如果掌握一套规律的话,会轻松许多.我将网上这些博主的文章进行一个梳理总结,最 ...
- Python进阶:理解元类创建类ABCMeta
Python进阶:Python进阶:理解元类创建类ABCMeta 一.理解元类(Meta class) 1.1 元类直观理解 1.2 Python官方文档给出的元类描述 二.理解抽象基类(ABC, A ...
- Python(迭代、三元表达式、列表生成、生成器、迭代器)
迭代 什么是迭代1 重复2 下次重复一定是基于上一次的结果而来 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration). 在 ...
- Python高级特性(切片,迭代,列表生成式,生成器,迭代器)
掌握了Python的数据类型.语句和函数,基本上就可以编写出很多有用的程序了. 比如构造一个1, 3, 5, 7, ..., 99的列表,可以通过循环实现: L = [] n = 1 while n ...
- python class 是否存在某个变量_一文抵十课,考验你的Python变量是否理解透彻了
变量是编程的基础概念,Python 的变量也看似很简单,但是如果理解不当,生搬硬套,可能会遇到一些麻烦. 下面用 10 个代码示例展示 Python 的 变量 本质. 快来看看你对 Python 的变 ...
- python args kwargs 理解_*args和**kwargs在python中的作用
我发现PYTHON新手在理解*args和**kwargs这两个魔法变量的时候有些困难.他们到底是什么呢? 首先,我先告诉大家一件事情,完整地写*args和**kwargs是不必要的,我们可以只写*和* ...
- python基础入门(6)之列表
目录 一.Python列表 一.列表基本知识 1)创建列表 2)列出表值 3)列表长度 4)列表项 - 数据类型 5)Python 集合(数组) 二.访问列表 1.正常索引 2)负索引 3)索引范围 ...
最新文章
- 把eclipse从英文调整为中文
- 解决“由于应用程序的配置不正确,应用程序未能启动,重新安装应用程序可能会纠正这个问题”...
- java session 是什么意思_Java:Session详解
- redis 分布式锁 看门狗_漫谈分布式锁之Redis实现
- vue 获取元素高度
- 腾讯一面总结-web前端-2018.4.11
- js调用php会提前加载,为什么js代码里调用了php变量运行就明显变慢了
- “聆听”升级,阿里云智能喜迎首席聆听官
- 彻底弄明白之数据结构中的排序七大算法-java实现
- [Linux学习]更改默认启动图形界面或命令行
- dnn305的一个bug
- 北斗导航 | 基于奇偶矢量法的RAIM之SSE探索(附奇偶矢量法源代码)
- mac m1 安装svn/subversion
- 摩拜开锁系统是用什么服务器,摩拜昨晨现“开锁难” 市民:系统需更稳定
- c语言编fft算法程序,FFT算法的C语言编程
- HTML5+CSS3 Pink老师课后作业——小米logo过渡切换的实现
- 最轻松mflac转flac、mp3方法
- 上传文件到云服务器一般用什么软件?
- 怎么把手机屏幕投射镜像到电脑上面?
- 合并两个有序表(C语言)
热门文章
- 2013级C++第2周(春)项目——结构体应用大体验
- 实现黑客帝国中的代码雨 快进来学(附源代码)
- 项目合同管理:合同分类、费用支付方式、违约责任承担方式、签订注意事项、合同索赔流程
- 前端开发实习面试题(Vue篇)
- Photoshop如何调整证件照背景色
- android x86触屏驱动下载,农步祥作品 - 使用台式机和触摸屏玩Android X86 [Soomal]
- 【张朝阳的物理课笔记】 1. 力,牛顿定律,飞船角速度
- am355x armlinux 移植openssh
- sklearn实现决策树
- html caption属性的值,如何设置caption属性