『无为则无心』Python面向对象 — 54、重写和super()函数
1、重写
在子类中如果有和父类同名的方法,则通过子类实例去调用该方法时,会调用子类中的该方法而不是父类的方法,这个特点我们成为叫做方法的重写(覆盖:override
)。
故事继续:徒弟掌握了师父和学院派技术后,自己潜心钻研出自己的独门配方的一套全新的煎饼果子技术。
# 1.创建师父类,属性和方法
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 2.创建学院派类 属性和方法
class School(object):
def __init__(self):
self.kongfu = '[学院派煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 3.独创配方
class Prentice(School, Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 4. 用徒弟类创建对象,调用实例属性和方法
tudi = Prentice()
print(tudi.kongfu)
tudi.make_cake()
"""
输出结果
[独创煎饼果子配方]
运用[独创煎饼果子配方]制作煎饼果子
"""
结论:子类和父类具有同名属性和方法,默认使用子类的同名属性和方法。
拓展:
当我们调用一个对象的方法时,会优先去当前对象中寻找是否具有该方法,如果有则直接调用。
如果没有,则去当前对象的父类中寻找,如果父类中有则直接调用父类中的方法。
如果没有,则去父类的父类中寻找,以此类推,直到找到object,如果依然没有找到,则报错。
2、super()函数
在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super()
函数来实现。
实际需求就是:子类调用父类的同名方法和属性。
方式一
故事继续:虽然自己独创的煎饼果子配方非常受欢迎,但是还是有顾客都希望也能吃到古法和学院技术的煎饼果子。
# 1.创建师父类,属性和方法
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 2. 定义徒弟类,继承师父类
# 添加和父类同名的属性和方法
class Prentice(Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
# 子类的make_cake(self)方法
def make_cake(self):
"""
加自己的初始化的原因:
如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,
如果不加这个自己的初始化,
kongfu属性值是上一次调用的init内的kongfu属性值
执行方式如下:
# 创建一个子类对象
tudi = Prentice()
# 调用执行父类中的make_cake()方法
tudi.make_master_cake()
# 调用子类中的make_cake()
tudi.make_cake()
就能看到劫、结果。
所以在调用属性前,先调用自己子类的初始化,要记住。
"""
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 调用父类的make_cake()方法
# 子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装
# 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
def make_master_cake(self):
# 父类类名.函数()
# 再次调用初始化的原因:这里想要调用父类的同名方法和属性,
# 属性在init初始化位置,所以需要再次调用init
Master.__init__(self)
Master.make_cake(self)
# 3 . 用徒弟类创建对象,调用实例属性和方法
# 创建一个子类对象
tudi = Prentice()
# 调用执行父类中的make_cake()方法
tudi.make_master_cake()
# 调用子类中的make_cake()
tudi.make_cake()
"""
输出结果:
运用[古法煎饼果子配方]制作煎饼果子
运用[独创煎饼果子配方]制作煎饼果子
"""
方式一:make_master_cake()
方法中的代码冗余;父类类名如果变化,那么在子类中会涉及多处修改,另外,Python是允许多继承的语言,如上所示的方法在多继承时就需要重复写多次,显得累赘。为了解决这些问题,Python提供了super()
函数解决此问题。
方式二
使用super()
函数调用父类中的同名方法。
# 1.创建师父类,属性和方法
class Master(object):
def __init__(self):
self.kongfu = '[古法煎饼果子配方]'
def make_cake(self):
print(f'运用{self.kongfu}制作煎饼果子')
# 2. 定义徒弟类,继承师父类
# 添加和父类同名的属性和方法
class Prentice(Master):
def __init__(self):
self.kongfu = '[独创煎饼果子配方]'
# 子类的make_cake(self)方法
def make_cake(self):
self.__init__()
print(f'运用{self.kongfu}制作煎饼果子')
# 调用父类的make_cake()方法
# 子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装
# 调用父类方法,但是为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
def make_master_cake(self):
# 方法二: super()
# super函数需要传递的参数:(当前类名, self)前边是类名,后边是对象
# 方式一: super(当前类名, self).函数()
# super(Prentice, self).__init__()
# super(Prentice, self).make_cake()
# 方式二; 简便方法,使用super().函数(),参数可省略。
super().__init__()
super().make_cake()
# 3 . 用徒弟类创建对象,调用实例属性和方法
# 创建一个子类对象
tudi = Prentice()
# 调用执行父类中的make_cake()方法
tudi.make_master_cake()
# 调用子类中的make_cake()
tudi.make_cake()
"""
输出结果:
运用[古法煎饼果子配方]制作煎饼果子
运用[独创煎饼果子配方]制作煎饼果子
"""
注意:使用super()
函数可以自动查找父类。调用顺序遵循 __mro__
类属性的顺序。比较适合单继承使用。
__mro__
内置类属性说明
在Python中快速查看一个类的所继承的父类,以及父类的层级关系的方法,返回的结果是一个元组。
# 如上边示例
# 语法:类名.__mro__
print(Prentice.__mro__)
"""
输出结果:
(<class '__main__.Prentice'>, <class '__main__.Master'>, <class 'object'>)
可以看到返回的是一个元组,
`super()`函数在这个元组的类中,依次查找相关属性或方法。
"""
『无为则无心』Python面向对象 — 54、重写和super()函数的更多相关文章
- 『无为则无心』Python面向对象 — 46、类和对象
目录 1.理解类和对象 2.类 3.对象 4.Python中的对象 5.类和对象的定义 (1)定义类 (2)创建对象 (3)练习 6.拓展:isinstance() 函数 1.理解类和对象 (1)类和 ...
- 『无为则无心』Python面向对象 — 51、私有成员变量(类中数据的封装)
目录 1.私有成员变量介绍 (1)私有成员变量概念 (2)私有成员变量特点 (3)私有成员变量体验 2.属性私有化工作原理 3.定义成员变量的标识符规范 4.私有成员变量的获取和设置方式 1.私有成员 ...
- 『无为则无心』Python面向对象 — 53、对Python中封装的介绍
目录 1.继承的概念 2.继承的好处 3.继承体验 4.单继承 5.多继承 1.继承的概念 在Python中,如果两个类存在父子级别的继承关系,子类中即便没有任何属性和方法,此时创建一个子类对象,那么 ...
- 『无为则无心』Python面向对象 — 45、面向对象编程
目录 1.面向对象编程的概念 2.面向对象编程和面向过程编程的区别 (1)面向过程编程 (2)面向对象编程 3.举例理解面向对象 4.Python的面向对象编程 5.面向对象的几大核心特性 1.面向对 ...
- 『无为则无心』Python面向对象 — 52、私有成员方法(类中行为的封装)
Python对于类的成员没有严格的访问控制限制,这与其他面向对象的编程语言是有所区别的. 关于私有方法其实和私有属性差不多,有如下要点: 1.通常我们约定,两个下划线开头的方法是私有方法. 2.类内部 ...
- 『无为则无心』Python面向对象 — 56、Python多态
目录 1.Python中的多态 (1)多态的定义 (2)多态的好处 (3)多态实现步骤 2.体验多态 1.Python中的多态 (1)多态的定义 多态是一种使用对象的方式,子类重写父类方法,不同的子类 ...
- 『无为则无心』Python面向对象 — 47、Python中的self详解
目录 1.self的作用 2.self的使用注意事项 (1)self代表类的实例,而非类 (2)self不必非写成self,只是一种规范. (3)类中方法的形参中一定要写self,包括内置函数 (4) ...
- 『无为则无心』Python面向对象 — 55、多层继承和继承中的私有成员
目录 1.Python支持多层继承 (1)多层继承实现 (2)多层继承和多重继承区别 2.继承中的私有成员 (1)继承中父类私有属性和私有方法 (2)获取和修改私有属性值 1.Python支持多层继承 ...
- 『无为则无心』Python面向对象 — 58、类方法和静态方法
目录 1.实例方法 2.类方法 (1)类方法特点 (2)类方法使用场景 3.静态方法 (1)静态方法特点 (2)静态方法使用场景 1.实例方法 实例方法既可以调用静态方法也可以调用类方法. # 定义一 ...
随机推荐
- Android官方文档翻译 十七 4.1Starting an Activity
Starting an Activity 开启一个Activity This lesson teaches you to 这节课教给你 Understand the Lifecycle Callbac ...
- 《剑指offer》面试题14- I. 剪绳子
问题描述 给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m.n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m] .请问 k[0]*k[1]* ...
- CAS学习笔记四:CAS单点登出流程
CAS 的登出包含两种情况,一种是CAS客户端登出,另一种是CAS单点登出,使用流程图说明这两者的不同.(一图胜千言) 总结自官方文档 CAS客户端登出流程 如图,客户端的登出仅仅是过期当前用户与客户 ...
- 【记录一个问题】go.mod中使用replace后,编译出现神奇的错误:
biz\child.go:5:2: imported and not used: "xxx.com/start/common/src/polaris" as biz biz\chi ...
- 一些Markdown扩展语法
相信很多人跟我一样,对Markdown是"一知半解",会打一点,知道一点,但是其实从没花哪怕一分钟了解过.其实除了标题粗体插入代码,Markdown还有很多有趣的基础语法和扩展语法 ...
- React教程
教程 一.demo <!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> &l ...
- echarts的通用属性的介绍
通常做数据可视化时,会用到统计图,这里我使用的是Echarts,对于第一次用的人来说,还是有点难度的,主要是里面的属性太多,看的头痛,这里我自己做个笔记 这里的配置项手册里面就是查找各种属性了,在Ec ...
- java多态成员变量、成员函数(非静态)、静态函数特点
1 package face_09; 2 3 /* 4 * 多态时, 5 * 成员的特点: 6 * 1,成员变量. 7 * 编译时:参考引用型变量所属类中的是否有调用的成员变量,有,编译通过:没有,编 ...
- 使用Termux并与ubuntu建立ssh连接
什么是Termux? Termux是一个Android终端仿真器和Linux环境应用程序,直接工作,无需根目录或设置.一个最小的基本系统被自动安装-额外的软件包可以使用APT软件包管理器来使用.不需要 ...
- Kubernetes的Controller进阶(十二)
一.Controller 既然学习了Pod进阶,对于管理Pod的Controller肯定也要进阶一下,之前我们已经学习过的Controller有RC.RS和Deployment,除此之外还有吗,如果感 ...