深入理解Python 关于supper 的 用法和原理
一、前言
Python 面向对象中有继承这个概念,初学时感觉很牛逼,里面也有个super类,经常见到,最近做一些题才算是理解了。特地记录分享给后来研究的小伙伴,毕竟现在小学生都开始学了(滑稽脸)
二、代码
直接上干货,能把下面一个问题全答对,后面就不用看了。
class A(): def go(self): print ("go A go!") def stop(self): print ("stop A stop!") def pause(self): raise Exception("Not Implemented") class B(A): def go(self): super(B, self).go() print ("go B go!") class C(A): def go(self): super(C, self).go() print ("go C go!") def stop(self): super(C, self).stop() print ("stop C stop!") class D(B,C): def go(self): super(D, self).go() print ("go D go!") def stop(self): super(D, self).stop() print ("stop D stop!") def pause(self): print ("wait D wait!") class E(B,C): pass a = A() b = B() c = C() d = D() e = E() # 说明下列代码的输出结果 a.go() print('--------') b.go() print('--------') c.go() print('--------') d.go() print('--------') e.go() print('--------') a.stop() print('--------') b.stop() print('--------') c.stop() print('--------') d.stop() print('--------') e.stop() print(D.mro()) a.pause() b.pause() c.pause() d.pause() e.pause()
当然,直接运行就有答案了,还是要仔细想一下,反正看到我第一次跑出的结果的时候,我都不敢相信自己的眼睛。
step1:
几个概念:
继承的功能:父类的代码重用
多态的功能:同一方法对不同类型的对象会有相应的结果
开闭原则:对扩展开放,对修改封闭
super类功能:新式类实现广度优先的不重复的调用父类,解决了钻石继承(多继承)的难题
step2:
super实现原理:通过c3算法,生成mro(method resolution order)列表,根据列表中元素顺序查询调用
新式类调用顺序为广度优先,旧式类为深度优先
step3:
个人理解:
1.调用了父类的方法,出入的是子类的实例对象
2.新式类子类(A,B),A就在B之前
3.super类似于嵌套的一种设计,当代码执行到super实例化后,先去找同级父类,若没有其余父类,再执行自身父类,再往下走,
简洁点的三个原则就是:
子类在父类前,所有类不重复调用,从左到右
理解了以上的说法,题目就没问题了。
也不用跑了,答案如下:
a.go()# go A go! b.go()# go A go!# go B go! c.go()# go A go!# go C go! d.go()# go A go!# go C go!# go B go!# go D go! e.go()# go A go!# go C go!# go B go! a.stop()# stop A stop! b.stop()# stop A stop! c.stop()# stop A stop!# stop C stop! d.stop()# stop A stop!# stop C stop!# stop D stop! e.stop()# stop A stop! a.pause()# ... Exception: Not Implemented b.pause()# ... Exception: Not Implemented c.pause()# ... Exception: Not Implemented d.pause()# wait D wait! e.pause()# ...Exception: Not Implemented
看了答案,其实还有一点,父类抛异常的情况,如果子类有不抛异常的方法,异常就不抛出了,这个设计也会很有用。
这里就中间一个A,C,B,D的和网上常见的不太一样,促使我仔细研究了一下,其实就是个人理解第三条。
补充:
Python2 和Python3在这个问题上的差别
Python2 没有默认继承object
Python3 默认全部继承object类,都是新式类
Python2super调用 super(开始类名,self).函数名()
Python3 super().函数名()
关于调用父类函数传入子类实例的栗子举一个:
class A: def __init__(self): self.n = 2 def add(self, m): print('self is {0} @A.add'.format(self)) self.n += m class B(A): def __init__(self): self.n = 3 def add(self, m): print('self is {0} @B.add'.format(self)) super().add(m) print('newb') self.n += 3 class C(A): def __init__(self): self.n = 4 def add(self, m): print('self is {0} @C.add'.format(self)) super().add(m) print('newc') self.n += 4 class D(B, C): def __init__(self): self.n = 5 def add(self, m): print('self is {0} @D.add'.format(self)) super().add(m) self.n += 5 d = D() d.add(2) print(d.n)
总结
以上所述是小编给大家介绍的Python 关于supper 的 用法和原理,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!
- 零基础学编程027:站在巨人的肩膀上
- 群分享:Markdown + CSS 实现微信公众号排版
- Android 蓝牙操作详解
- Linq to xml 操作带命名空间的xml
- Android 操作Sqlite
- 零基础学编程039:生成群文章目录(2)
- Android中的AutoCompleteTextView的使用
- 深度学习以及卷积基础
- Android 控件:使用下拉列表框--Spinner
- 层层升入:SQL极限调优之一次更新操作的N种优化可能
- 零基础学编程037:小数据分析
- 【干货】圣诞老人是否真实存在?训练Tensorflow的对象检测API能够告诉你答案
- 排序含有数字的字符串:一个巧妙地方法
- wpf 控件大小随窗体大小改变而改变
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Qt读写文件(2种方式)实现详解
- 字符串匹配 - KMP算法
- c# 判断文件是否发生了变化
- C# 用IrisSkin4.dll美化你的WinForm
- Oracle参数解析(shared_pool_size)
- C# GTS四轴运动控制器实例(固高科技步进电机不带编码器)
- Oracle参数解析(pre_page_sga)
- C#简单爬取数据(.NET使用HTML解析器NSoup和正则两种方式匹配数据)
- [WPF] WPF做的漂亮的登陆界面[附源码]
- C#自定义控件的创建
- Oracle参数解析(processor_group_name)
- [Oracle故障处理]记一次PX msg pool 4031错误的处理
- WPF的布局-Grid(表格布局)
- C# 通过遍历设置控件属性
- C# 软件开机启动