Self-study Python Fish-C Note19 P62to63

类和对象 (part 2)

本节主要介绍 类和对象的构造函数、重写、钻石继承、Mixin及案例源码剖析(原视频P62-63)\

构造函数

之前我们在函数章节里说,函数是可以通过参数来进行个性化定制的。类在实例化的时候其实也是支持个性化定制对象的。
定义类的时候定义一个构造函数,构造函数:__init__()
我们只需要在类中定义 __init__() 方法,那么就可以在实例化对象的同时实现个性化的定制。
实例:

class C:def __init__(self,x,y): # 这里写上构造函数,构造函数 __init__ 第一个参数是 self(必须)。之后两个参数是实例化对象的两个参数 x,yself.x = x # 注意这里 等号左边的 self.x 是绑定到实例化对象里面的x属性,等号右边的x是传进来的 x 参数self.y = ydef add(self):return self.x + self.ydef mul(self):return self.x * self.yc1 = C(2,3) # 即我们在实例化的时候,就顺带着把对象的两个变量给安排进去了
print(c1.add())
print(c1.mul()) 
c1.__dict__ #我们这里内省一下,可以看到传入的参数都成了c1的属性
5
6{'x': 2, 'y': 3}
# 传入 不同参数 测试一下:
c2 = C(4,5)
print(c2.add())
print(c2.mul())
c2.__dict__
9
20{'x': 4, 'y': 5}

重写 与 钻石继承

重写

如果我们对于父类的某个属性和方法不满意的话,完全可以写一个同名的属性或方法对其进行覆盖。这种行为我们就称之为子类对父类的重写。
实例:

# 我们重写一个类D(继承自上面的类C),但不满足其只有两个参数,我们要多写一个参数
class D(C):def __init__(self,x,y,z):C.__init__(self,x,y) # 这一句等于:# self.x=x# self.y=yself.z=zdef add(self):return C.add(self)+self.zdef mul(self):return C.mul(self)*self.zd1 = D(2,3,4)
print(d1.add())
print(d1.mul())
d1.__dict__
9
24{'x': 2, 'y': 3, 'z': 4}

这种直接通过类名访问类里边的方法的做法,称之为调用未绑定的父类方法。 这种方法比较直接但没错,有时候可能会造成钻石继承的问题!

钻石继承

实例:

class A:def __init__(self):print('A.__init__ 调用一次')# we define other 2 classes, B1 and B2, and they all inherit from A
class B1(A):def __init__(self):A.__init__(self)print('B1.__init__ 调用一次')class B2(A):def __init__(self):A.__init__(self)print('B2.__init__ 调用一次')# we define class C, which inherit from B1 and B2 at the same time
class C(B1,B2):def __init__(self):B1.__init__(self) # 我么这里调用一下类C父类的 __init__B2.__init__(self)print('C.__init__ 调用一次')# we see what happened
c1=C()
A.__init__ 调用一次
B1.__init__ 调用一次
A.__init__ 调用一次
B2.__init__ 调用一次
C.__init__ 调用一次

上面的示例就是一个钻石继承发生的例子,我们可以发现当我们实例化 c1=C() 的时候,A.__init__ 被重复调用了两次。
在这里插入图片描述

究其原因:类 C 是同时继承自 类B1 和 类 B2 的。类B1 和 类 B2 又是继承自 类A 的。所以当我们 类C 去调用 类B1 和 类 B2 的构造函数的时候,类A的构造函数也会被跟着调用两次(B1一次,B2一次)。
与之对应,可以调用 super() 函数 来解决钻石继承的问题。

super() 函数

super() 函数 能够在父类中搜索指定的方法,并自动绑定好 self 参数
我们修改一下上面 类B1,类B2,类C的代码:

class B1(A):def __init__(self):super().__init__() # 这里我们用 super(),不再用未绑定的父类方法。# 因为我们有写清继承关系 B1是继承自A,super()自动会去搜寻父类。# 同时 self 也不用显示的传入了, super() 会解决print('B1.__init__ 调用一次')class B2(A):def __init__(self):super().__init__()print('B2.__init__ 调用一次')class C(B1,B2):def __init__(self):super().__init__() # 这里不用去写 B1 B2 了,它自己会去遍历print('C.__init__ 调用一次')# we see what happened
c1=C()
A.__init__ 调用一次
B2.__init__ 调用一次
B1.__init__ 调用一次
C.__init__ 调用一次

此时结果就不会重复的调用了,所以我们使用 super() 函数去查找父类的方法,他就会自动按照 MRO 顺序去搜索父类的相关方法,并且自动避免重复调用的问题。\

MRO 顺序

MRO (method resolution order) 顺序(方法解析顺序): 在我们之前将多继承的时候说过,如果出现同名的属性或方法,Python 会有一个明确的查找覆盖的顺序,这个顺序就是 MRO 顺序。
如果我们要查找一个类的 MRO 顺序,有两种方法:
法1:

mro() 方法
C.mro()
[__main__.C, __main__.B1, __main__.B2, __main__.A, object]

其中 object 是所有类的基类,就算我们不写,也会被隐式的继承。

B1.mro()
[__main__.B1, __main__.A, object]
__mro__ 属性
B1.__mro__
(__main__.B1, __main__.A, object)

Mixin 案例源码剖析

Mixin 这个概念就是 mix-in,是一种设计模式(设计模式就是利用编程语言已有的特性,针对面向对象开发过程中反复出现的问题,而设计出来的解决方案)。
Mixin 示例:
原来代码:

class Animal: # 我们先定义了一个 Animal 类def __init__(self,name,age): # Animal 类 有构造函数,构造函数需要传入 name 和 ageself.name = nameself.age = agedef say(self): print(f'my name is {self.name}, now I am {self.age} years old')class Pig(Animal): # 定义 Pig 类 继承 Animal 类def special(self):print('I am doing xxx')p1 = Pig('A',5)
p1.say()
p1.special()
my name is A, now I am 5 years old
I am doing xxx

我们现在想加一个功能,让 p1 有飞的功能。其实可以写一个 飞 的功能,让 Pig 去继承他,继承一个类就可以使用类里面的方法和属性。

class Flymixin: # mixin 不是必要的,这里写上只是加以区分def fly(self):print('I am flying')# 使用多继承,插入到 Pig 类里
class Pig(Flymixin, Animal): def special(self):print('I am doing xxx')p1 = Pig('A',5)
p1.say()
p1.special()
p1.fly()
my name is A, now I am 5 years old
I am doing xxx
I am flying

这其实就是游戏外挂的思路。下面我们有一个更复杂的例子,加深我们理解这个技巧:

class Displayer:def display(self, message):print(message)class LoggerMixin:def log(self, message, filename='logfile.txt'):with open(filename,'a') as f:f.write(message)def display(self, message):super().display(message)self.log(message)class MySubClass(LoggerMixin, Displayer):def log(self, message):super().log(message,filename='subclasslog.txt')subclass = MySubClass()
subclass.display('this is a test')
this is a test

运行结果除了打印了 :this is a test,还生成了一个 ‘subclasslog.txt’ 的文件里面内容:

this is a test

详解:

subclass = MySubClass()
subclass.display('this is a test')

首先,类 MySubClass 实例化一个对象 subclass。调用 display() 方法,参数 'this is a test'
那么调用的 display() 方法 是谁的?
首先不可能是自己 MySubClass 的,因为里面没有这个方法。于是我们要从父类里面查找,这里父类有两个一个是 LoggerMixin (一般我们看到起名以Mixin结尾的就是Mixin 设计模式,是为了添加某个功能后期插上去的(想象成游戏外挂));另一个父类是 Displayer
根据先左后右的原则, Python会先去类 LoggerMixin 里查找display() 方法,然后找到:

class LoggerMixin:......def display(self, message):super().display(message)self.log(message)

这里面的 display() 方法带 message 参数,就是说这里会把 'this is a test' 传递。这里方法实现的第一句,super().display(message)super() 就会去父类里面查找对应的方法。但是其实这里 类LoggerMixin 没有写父类,所以默认应该是 Object。
但是 Object 作为一个总的基类,是不会有 display() 方法的。这里是因为,super() 函数是严重依赖 MRO 顺序的,我们可以看一下 MySubClass 的 MRO 顺序:

MySubClass.mro()
[__main__.MySubClass, __main__.LoggerMixin, __main__.Displayer, object]

所以我们在类 LoggerMixin 里调用 super() 函数,它会先去类 Displayer 里查找,而不是 object。所以:

class LoggerMixin:......def display(self, message):super().display(message)self.log(message)

第一句 super().display(message) 就是去调用类 Displayer 里面的display() 方法。
第二句 self.log(message),这里面 log() 方法是谁的?这里取决于 self。这里 self 就是 subclass 这个对象本身(绑定)。subclass 是 类MySubClass 的实例化对象。且 类MySubClass 里面刚好有 log() 方法:

class MySubClass(LoggerMixin, Displayer):def log(self, message):super().log(message,filename='subclasslog.txt')

这里面又有 super() 函数,那么按照 MRO 原则去 LoggerMixin 里找:

class LoggerMixin:def log(self, message, filename='logfile.txt'):with open(filename,'a') as f:f.write(message)

这里 log() 方法就是创建一个文件,并追加保存 message 信息。

附言:
题目:Self-study Python Fish-C Note-19 P62-P63
本文为自学B站上鱼C的python课程随手做的笔记。一些概念和例子我个人为更好的理解做了些查询和补充
因本人水平有限,如有任何问题,欢迎大家批评指正!
原视频链接:https://www.bilibili.com/video/BV1c4411e77t?p=8

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1523523.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

idea的springboot里面的resources是什么

在IDEA(IntelliJ IDEA)中的Spring Boot项目中,resources目录扮演着非常重要的角色。这个目录主要用于存放项目的非代码资源,包括但不限于配置文件、静态资源文件(如图片、CSS、JavaScript等)、模板文件&…

如何用c++判断一个类型是vector

如何用c判断一个类型是vector 我们使用模板元编程来搞定 这里我们可以定义一个模板结构体 is_std_vector,并对其进行特化,以便专门处理 std::vector 类型。 . 下面是详细的实现和使用示例。 实现 is_std_vector 类型, 继承自false_type 首先&#xff…

EvoSuite使用总结

1.安装EvoSuite插件 以IDEA为例,在Plugins栏搜索EvoSuite后点击install,安装完成后重启IDEA 2.使用EvoSuite 选中文件右键选择Run EvoSuite 生成成功可以看到如下提示: 注意事项: 生成路径:src/test/java 使用juni…

数智时代敲门砖:华为云MaaS服务让中小企业AI应用如此简单

文|白 鸽 编|王一粟 19.9元的数字人、29.9元的云数据库、195元10卡时包的MaaS大模型服务...... 堪称企业级“双十一”的华为云828营销季,带着一众AI应用产品和云服务,杀疯了。 云计算叠加大模型的价格战,也正式进入…

HTTPS理论(SSL/TLS)

SSL安全套接层协议 为互联网通信提供加密和身份认证SSL3.0有漏洞,被TLS取代基于TCP的协议工作原理 握手:客户端hello;服务器hello(发送数字证书)(协商ssl版本,加密算法)数据传输连接…

JS笔记

9.3 1.数据类型 1.1.Object 对象 对象:一切皆对象 面向过程:按照时间的发生顺序,从上往下依次执行 对象对象:指挥对象做某件事 1.2.数据类型的检测 1.3.数据类型转换 1.自动转换:js会通过关系运算符&#xff0c…

ai聊天软件哪个好用?分享5款实用的智能聊天软件

从文字到语音,再到现在的智能AI聊天软件,我们见证了沟通方式的不断演进。 每天,我们都需要与家人、朋友、同事进行交流,而AI聊天软件的出现,无疑为我们的对话增添了一抹智能色彩。 那么,ai聊天软件下载哪…

Kettle--发送邮件

目录 新建转换 执行成功 新建demo 作业job 发送邮件配置 邮件服务器: 授权码获得 以163邮箱为例 新建转换 执行成功 新建demo 作业job 发送邮件配置 确定发件人和收件人邮箱 服务器设置 邮件服务器: 邮件服务商SMTP服务器地址SMTP端口(…

图像边缘检测技术详解:利用OpenCV实现Sobel算子

图像边缘检测技术详解:利用OpenCV实现Sobel算子 前言Sobel算子的原理代码演示结果展示结语 前言 在数字图像处理的广阔领域中,边缘检测技术扮演着至关重要的角色。无论是在科学研究、工业自动化,还是在日常生活中的智能设备中,我们…

我的大模型岗位面试总结!太卷了!!!—我面试了24家大模型岗位 只拿了9个offer!

这段时间面试了很多家(共24家,9个offer,简历拒了4家,剩下是面试后拒的),也学到了超级多东西。 大模型这方向真的卷,面试时好多新模型,新paper疯狂出,东西出的比我读的快…

HiGPT:异构图语言模型的突破

人工智能咨询培训老师叶梓 转载标明出处 人工智能领域的一大挑战是如何从海量复杂的数据中提取有价值的信息,特别是在处理异构图数据时。异构图由多种类型的节点和边组成,它们之间的相互关系丰富而复杂。传统的图神经网络(GNNs)在…

年薪80万,成功入职字节跳动!

前言: 最近AI相关就业岗位爆了。。。无论是**华为、**百度、阿里、字节等互联网巨头,还是中小型的科技公司都在高薪挖 AI 人才。 上周找 字节的面试官朋友(职级3-1)要来了几套高质量AI****内部资料和2024吴恩达机器学习资料。既…

DeepMind MuJoCo——生成动态场景中的物体运动视频,模拟物理现象和动作生成

一、DeepMind MuJoCo介绍 DeepMind MuJoCo(Multi-Joint dynamics with Contact)是一个由 DeepMind 开发的高效物理仿真引擎,专门用于模拟具有复杂物理交互的机器人和物理系统。MuJoCo 能够在实时和非实时环境下进行高精度的物理仿真&#xf…

护眼台灯哪个牌子最好?五款央视公认最好的护眼灯分享

小时候,对正确用眼知识一无所知,也不明白何种光线环境对眼睛最为友善,结果如今的近视度数已濒临千度大关。虽然早已习惯佩戴眼镜的生活,但近视所带来的诸多不便仍旧在日常生活中无处不在。因此,对于家中孩子的视力健康…

开源的工作流系统突出优点总结

当前,想要实现高效率的办公,可以一起来了解低代码技术平台、开源的工作流系统的相关特点和功能优势。作为较受职场喜爱的平台产品,低代码技术平台拥有可视化才做界面、灵活、好维护操作等多个优势特点,在推动企业流程化办公的过程…

掀起社交娱乐新浪潮!AI如何应用到短视频APP?

随着人工智能技术的迅速发展和全球社交媒体用户的增长,AI视频生成应用正逐渐成为短视频社交媒体中的关键工具。AI工具不仅可以提高内容的创造效率,还能为用户带来全新的互动体验。 人工智能(AI)已经成为我们日常生活和工作中不可或…

街机 CAPCOM CPS2 中英文名字与驱动对照表

Part.I 简介 本文列举了街机 CPS2 中游戏的中英文名字与其驱动的对照,以帮助诸位更快地找到自己想玩的游戏。 注意:汉化版的街机模拟器 Kawaks 中游戏的中文名字是根据英文直译的,并不是习惯性的中文叫法。比如『三国志』英文名为『Warriors…

django企业开发实战-学习小结

写在前面 初次阅读此书是三年前,当时没经历过完整的项目 觉得这书就是扯淡 后来经历过项目加班与毒打 今天再翻开此书 觉得实乃不可多得之物 花些时间啃下来吧 django版本 3.2 本博客开源项目地址 kimsmith/django企业实战 (gitee.com) 有的代码因为版本混乱报错…

(一)SVG行业组件库描述

SVG教程 https://m.runoob.com/svg/菜鸟教程SVG 教程..https://m.runoob.com/svg/ 1、SVGO 1.1 konw是什么 用于优化SVG文件的Node.js库和命令行应用程序。 SVG文件,特别是那些从矢量编辑器导出的文件,通常包含大量冗余信息。这包括编辑器元数据、注…

51单片机-LED点阵屏实验(动态显示数据静态显示)

第一步喝口汤 个人理解:首先,这个LED点阵屏类似于数码的段选操作,这个LED点阵屏第一步就是利用595芯片来扩充IO,单片595就是能够把一个字节数据通过串行输入(一个IO输入),并行输出(…