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()函数的更多相关文章

  1. 『无为则无心』Python面向对象 — 46、类和对象

    目录 1.理解类和对象 2.类 3.对象 4.Python中的对象 5.类和对象的定义 (1)定义类 (2)创建对象 (3)练习 6.拓展:isinstance() 函数 1.理解类和对象 (1)类和 ...

  2. 『无为则无心』Python面向对象 — 51、私有成员变量(类中数据的封装)

    目录 1.私有成员变量介绍 (1)私有成员变量概念 (2)私有成员变量特点 (3)私有成员变量体验 2.属性私有化工作原理 3.定义成员变量的标识符规范 4.私有成员变量的获取和设置方式 1.私有成员 ...

  3. 『无为则无心』Python面向对象 — 53、对Python中封装的介绍

    目录 1.继承的概念 2.继承的好处 3.继承体验 4.单继承 5.多继承 1.继承的概念 在Python中,如果两个类存在父子级别的继承关系,子类中即便没有任何属性和方法,此时创建一个子类对象,那么 ...

  4. 『无为则无心』Python面向对象 — 45、面向对象编程

    目录 1.面向对象编程的概念 2.面向对象编程和面向过程编程的区别 (1)面向过程编程 (2)面向对象编程 3.举例理解面向对象 4.Python的面向对象编程 5.面向对象的几大核心特性 1.面向对 ...

  5. 『无为则无心』Python面向对象 — 52、私有成员方法(类中行为的封装)

    Python对于类的成员没有严格的访问控制限制,这与其他面向对象的编程语言是有所区别的. 关于私有方法其实和私有属性差不多,有如下要点: 1.通常我们约定,两个下划线开头的方法是私有方法. 2.类内部 ...

  6. 『无为则无心』Python面向对象 — 56、Python多态

    目录 1.Python中的多态 (1)多态的定义 (2)多态的好处 (3)多态实现步骤 2.体验多态 1.Python中的多态 (1)多态的定义 多态是一种使用对象的方式,子类重写父类方法,不同的子类 ...

  7. 『无为则无心』Python面向对象 — 47、Python中的self详解

    目录 1.self的作用 2.self的使用注意事项 (1)self代表类的实例,而非类 (2)self不必非写成self,只是一种规范. (3)类中方法的形参中一定要写self,包括内置函数 (4) ...

  8. 『无为则无心』Python面向对象 — 55、多层继承和继承中的私有成员

    目录 1.Python支持多层继承 (1)多层继承实现 (2)多层继承和多重继承区别 2.继承中的私有成员 (1)继承中父类私有属性和私有方法 (2)获取和修改私有属性值 1.Python支持多层继承 ...

  9. 『无为则无心』Python面向对象 — 58、类方法和静态方法

    目录 1.实例方法 2.类方法 (1)类方法特点 (2)类方法使用场景 3.静态方法 (1)静态方法特点 (2)静态方法使用场景 1.实例方法 实例方法既可以调用静态方法也可以调用类方法. # 定义一 ...

随机推荐

  1. 推荐一个最懂程序员的google插件

    0.前言 很多人应该也和我一样,使用google浏览器时,它的主页是真不咋地,太单调了,用起来贼不爽,想整它很久了 一打开就是上面的样子,让我看起来真心真心不爽 当然:为了这个不关技术的瞎犊子事情,曾 ...

  2. C语言字幕从外向中间汇聚

    演示数据中多个字符,从两端向中间移动,向中间汇聚 简单,粗暴,先上代码: Sleep()函数属于<windows.h>头文件中. sizeof()函数求右下标:数组内是数字时,求右下标要- ...

  3. Java中的标签语法(类似于C语言goto循环体)

    Java中的标签语法(少用) 101到150的质数 此法类似于C语言中的GOTO循环 public static void main(String[] args) { int count=0; //标 ...

  4. 【刷题-LeetCode】179 Largest Number

    Largest Number Given a list of non negative integers, arrange them such that they form the largest n ...

  5. luis使用手册

    Luis聊天机器人的使用 首先打开luis官网 图5.1  luis官网界面 图5.2  app应用管理界面 界面显示现有应用,显示它们的名称,语言,日期,以及使用次数.点击创建一个新的app应用. ...

  6. gin中间request body绑定到不同的结构体中

    1. 一般通过调用 c.Request.Body 方法绑定数据,但不能多次调用这个方法. package main import ( "fmt" "github.com/ ...

  7. linux不使用useradd添加新用户

    不使用useradd创建新的用户 1.进入用户特征信息:/etc/passwd 编辑: vim /etc/passwd 命令模式 :G 进入末行 进入编辑模式 :在最后添加新用户信息: 例:new_u ...

  8. 分子动力学模拟之基于自动微分的LINCS约束

    技术背景 在分子动力学模拟的过程中,考虑到运动过程实际上是遵守牛顿第二定律的.而牛顿第二定律告诉我们,粒子的动力学过程仅跟受到的力场有关系,但是在模拟的过程中,有一些参量我们是不希望他们被更新或者改变 ...

  9. foreEach 跳出循环

    const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; const _ = require('lodash'); let outArr = []; try { arr. ...

  10. C语言非阻塞式键盘监听

    监听键盘可以使用C语言的字符输入函数,例如 getchar.getch.getche 等,使用getche函数监听键盘的例子: #include <stdio.h> #include &l ...