Python 面向对象 之 多继承 MRO
Python 面向对象 之 多继承 MRO
回顾 - 类继承
关于子类的继承. 即子类可以继承父类的所有 方法及属性, 当子类要添加新功能或修改父类方法是, 可以在 子类对私进行 重写 overwrite . 大概回顾就行了, 这里也不想进行对过于基础性的问题进行探讨.
class A:
def __init__(self):
self.a = 10
self.b = 20
@staticmethod
def say_hello():
print("hello, world!")
在子类初始化的时候, 是需要手动调用父类的初始化方法来说明的, 语法为: 父类名.__ init__(self, ...)
class B(A):
def __init__(self, c, d):
"""重写父类__init__, 并新增d, e属性"""
self.c = c
self.d = d
A.__init__(self)
if __name__ == '__main__':
b = B(4, 5)
print(b.a)
print(b.d)
# output
10
5
当然也可以这用 super 关键字
class B(A):
def __init__(self, c, d):
"""重写父类__init__, 并新增d, e属性"""
self.c = c
self.d = d
super().__init__()
多继承 - Bug
这里主要演示一个, 多继承会出现的问题, 其实也不算bug吧, 原理我也没有仔细去推敲过哈, 先露出来看看吧.
class 父亲:
def __init__(self, name):
self.name = name
print("i am you father...")
class 长子(父亲):
def __init__(self, name, age):
self.age = age
父亲.__init__(self, name)
print(" i am eldest son")
class 次子(父亲):
def __init__(self, name, gender):
self.gender = gender
父亲.__init__(self, name)
print("i am the little son")
class 长孙(长子, 次子):
"""收养的哦"""
def __init__(self, name, age, gender):
长子.__init__(self, name, age)
次子.__init__(self, name, gender)
print("i am the sweet heart")
if __name__ == '__main__':
king = 长孙("小王子", 23, "F")
i am you father...
i am eldest son
i am you father... # 多执行了一次 ???
i am the little son
i am the sweet heart
卧槽. ....父类被执行了2次, 这感觉是浪费内存了呀, 嗯..有些紧张....
为啥会出现调用2次父类呢? 或者 如何只让调用一次就好呢 ? 分析一波上面这一段代码
长子.__init__(self, name, age) --> class 长子(父亲) --> class 父亲 -> print("father...")
次子.__init__(self, name, gender) --> class 次子(父亲) --> class 父亲 -> print("father...")
因此, 被调用了2次是没有问题的, 但这就带来一个新的优化问题: 浪费内存, 因为重复开辟空间了呀.
更一般地描述, 即在多继承的情况下, 父类的属性可能会出现被多次执行的情况, 这里仅仅是一个简单的case, 如果非常复杂的结果, 则会浪费非常多的内存和反复调用.
多继承 MRO
MRO - 引入
MRO 是 Pyhton 用来解决上面的这种, 会产生重复开辟空间的问题. 解决的办法是将 复杂结构上的所有类 全部映射到一个线性顺序上 (线性表), 这个顺序就是 MRO 顺序.
MRO表, 事先就调用好了, 按表的顺序调用, 从右到左
print(长孙.__mro__)
# output
(<class '__main__.长孙'>, <class '__main__.长子'>, <class '__main__.次子'>, <class '__main__.父亲'>, <class 'object'>)
这个线性表, 我从执行的角度来看, 就是个 栈, 父类在栈底, 小王子在栈顶 (Top) , 而搜索的顺序, 兄弟们, 定睛一看, 这一层, 一层第搜索,.... 感觉这就是 树的广度优先算法 呀.
MRO - super
官方已经把这个问题给解决了, 方式就是内置方法 super()
super() 方法在 Python 2 中是不一样的哦, Python3 更简洁, 直接拿父类的部件
super() - 多继承
class 父亲:
def __init__(self, name):
self.name = name
print("i am you father...")
# tips: 避免少接收参数, 则可都用上 *args, **kwargs 呀
class 长子(父亲):
def __init__(self, name, age, *args): # *args 接收 gender的.
self.age = age
super().__init__(name, *args)
print(" i am eldest son")
class 次子(父亲):
def __init__(self, name, gender):
self.gender = gender
super().__init__(name)
print("i am the little son")
class 长孙(长子, 次子):
"""收养的哦"""
def __init__(self, name, age, gender):
super().__init__(name, age, gender)
print("i am the sweet heart")
if __name__ == '__main__':
king = 长孙("小王子", 23, "F")
print(长孙.__mro__)
i am you father...
i am the little son
i am eldest son
i am the sweet heart
(<class '__main__.长孙'>, <class '__main__.长子'>, <class '__main__.次子'>, <class '__main__.父亲'>, <class 'object'>)
小结
- 多继承会产生重复调用的问题, 浪费内存空间
- MRO顺序是Python将类映射到一个线性表中来调用, 有序的, 能避免重复调用, 搜索算法目测是广度优先
- super 的理解和用法, 注意的点是传参的数量问题, 不明白, 可以都为通用形式 (* args, **kwargs)
还是稍微细节一波关于super(), 在单继承中, super().xxx 和 父类名. ... 二者是一样的效果, 但是在 多继承中, super() 使得父类方法只会执行一次, 传统的方法呢, 就出现了上面的那种 "钻石调用问题". 在使用 super()时候, 必须将参数全部传递, tips, 后面加上 * args * *kwargs.
从最初的例子看, 在单继承的时候呢, super()方法只能传递父类方法所需的参数, 似乎又不能 *args ** kwargs , 总是感觉这些设计, 搞得怪怪的, 都要 debug很久.多继承中呢, 一般用的比较多的是 **重写或继承 __ init__() **, 此处呢, super() 的优势 就显现出来了, 只要一行代码就可以将父类的都执行了, 嗯, 可能, 这就是 super() 要求传递所有参数的原因了吧.
至于用类的方式, 还是用 super(), 我感觉, 我平时写的脚本, 基本都用不到继承哈哈, 真是有点尴尬, 感觉满身的技能, 却总是让我干一些, 打杂的活...知己难寻呀, 才无聊到写博客, 抄博客, 抄段子, 抄代码....
Python 面向对象 之 多继承 MRO的更多相关文章
- Python面向对象三要素-继承(Inheritance)
Python面向对象三要素-继承(Inheritance) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.继承概述 1>.基本概念 前面我们学习了Python的面向对象三 ...
- Python面向对象中的继承、多态和封装
Python面向对象中的继承.多态和封装 一.面向对象的三大特性 封装:把很多数据封装到⼀个对象中,把固定功能的代码封装到⼀个代码块, 函数,对象, 打包成模块. 这都属于封装思想. 继承:⼦类可以⾃ ...
- Python - 面向对象编程 - 多继承
继承的详解 https://www.cnblogs.com/poloyy/p/15216652.html 这篇文章讲的都是单继承,Python 中还有多继承 Python 多继承的背景 大部分面向对象 ...
- Python面向对象之类的继承(2)
1.除了封装,Python面向对象还有继承这一功能,如下代码,这是简单的继承功能. class Animal: def chi(self): print(self.name+' 吃') def he( ...
- Python()- 面向对象三大特性----继承
继承: 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类(基类或超类),新建的类是所继承的类的(派生类或子类) 人类和狗 有相同的属性, 提取了一个__init__方法,在这 ...
- python 面向对象八 多继承
python是支持多继承的,在设计类的继承关系时,通常,主线都是单一继承下来的.但是,如果需要“混入”额外的功能,通过多重继承就可以实现,这种设计通常称之为MixIn. 为了更好地看出继承关系,以Mi ...
- python 面向对象及封装继承和多态
######装饰器######装饰器的概念 - 装饰器的实现是函数里面嵌套函数;- 装饰器的本质是一个函数, 它可以让其他函数在不需要做任何代码改动的前提下增加额外的功能;- 装饰器需要传递一个函数, ...
- python摸爬滚打之day20--多继承,MRO和C3算法
1.新式类和经典类 在python2.2之前, 基类如果不写(), 则表示为经典类; 在python2.2之后, 经典类不复存在, 只存在新式类. 如果基类谁都不继承的话, 则默认继承object. ...
- 47、Python面向对象中的继承有什么特点?
继承的优点: 1.建造系统中的类,避免重复操作. 2.新类经常是基于已经存在的类,这样就可以提升代码的复用程度. 继承的特点: 1.在继承中基类的构造(__init__()方法)不会被自动调用,它需要 ...
- Python面向对象,析构继承多态
析构: def __del__(self): print("del..run...") r1 = Role("xx") del r1 结果打印del..run. ...
随机推荐
- 职场软素质&算法工程师的硬素质--卓越的职场人需要的42种能力
经过自己在实际的工作中摸爬滚打,个人觉得一些方面的能力是非常重要的,可以让自己在职场中快速的脱颖而出,因此,从硬实力,软实力两个方面进行总结如下: 软实力: (1)解决问题的能力 (2)预估风险的能力 ...
- 2. 在Linux 当中安装 Nginx(13步) 下载&安装&启动(详细说明+附加详细截图说明)
2. 在Linux 当中安装 Nginx(13步) 下载&安装&启动(详细说明+附加详细截图说明) @ 目录 2. 在Linux 当中安装 Nginx(13步) 下载&安装&a ...
- manim边学边做--局部缩放的场景类
在动画制作中,尤其是数学和科学可视化领域,有时我们需要将观众的注意力集中在场景的某个特定部分. Manim提供了一个强大的工具 ZoomedScene,它允许我们在场景中创建一个独立的缩放视图,从而实 ...
- 安卓线性布局LinearLayout
1.weight权重解读 用法归纳: 按比例划分水平方向:将涉及到的View的android:width属性设置为0dp,然后设置为android weight属性设置比例即可. ` <Line ...
- CATIA许可证破解方法(CMD版)
<<< catia的DS License Server Administration后不会自动弹出GUI界面,就需要使用CMD来破解安装许可证. <<< 1. ca ...
- calico配置报错 kubelet.go:2855] "Container runtime network not ready"
前言 配置 calico 网络插件时,kubectl get node 报错: NoReady kubectl describe node node Name: node Roles: <non ...
- ubuntu apt 安装报错:Media change: please insert the disc labeled 'Ubuntu 20.04.5 LTS Focal Fossa - Release amd64 (20220831)' in the drive '/cdrom/' and press [Enter]
前言 如果你在 Ubuntu 上使用 apt 安装软件包时遇到 "Media change: please insert the disc labeled ..." 的错误消息,这 ...
- JOKER可视化开发工具迎来重大更新
为紧跟行业前沿趋势,满足开发者日益增长的需求,我们于2025年3月13日对平台开展了全方位升级.此次更新聚焦前端交互的便捷性.服务端功能的强大性以及通用操作的流畅性,在多方面进行了深度优化.尤为值得一 ...
- 关于SIFT,GIFT在旋转不变性上的对比实验
目录 关于SIFT,GIFT在旋转不变性上的对比实验 回顾 准确率测试 总结 核心代码 关于SIFT,GIFT在旋转不变性上的对比实验 这篇文章不讨论SIFT,GIFT的实现原理,只从最终匹配结果的准 ...
- Audio DSP 链接脚本文件解析
上篇文章(智能手表音乐播放功耗的优化)讲了怎么优化音乐场景下的功耗,其中第二点是优化memory的布局.那么在哪里优化memory的布局呢?就是在本文要讲的链接脚本(ld)文件里.作为audio DS ...