继承与组合

【一】什么是继承

  • 继承就是创建新类的一种方式,这个新类可以继承一个或者多个其他类的属性

  • 新的类如果有自己属性,那就叫派生

【二】继承的优点

  • 可以继承父类的所有属性和方法,这样就可以实现代码去重。

【三】继承方式

  • 单继承:继承一个父类的子类

  • 多继承:继承多个父类的子类

例如:

class Student(School):
# 被继承的类叫父类 School
# 新类就叫子类  Student

【四】单继承

class Person(object):height = 180weight = 60
​
# 继承Person
class Student(Person):def __init__(self, name):self.name = name
​def tell_me(self):print(f"我是{self.name},我的身高是{self.height},我的体重是{self.weight}")
​
​
stu1 = Student("knight")
stu1.tell_me()

【五】多继承

class Person(object):height = 180weight = 60
​
​
class School(object):school_name = '家里蹲'
​
# 继承两个父类,Person和School
class Teacher(Person,School):def __init__(self, name):self.name = name
​def tell_me(self):print(f"我是{self.name},我所在的学校是{self.school_name},我的身高是{self.height},我的体重是{self.weight}")
​
​
tea1 = Teacher("knight")
tea1.tell_me()

【六】查看当前继承的父类状况

# base 只打印一个当前继承的父类,如果当前继承了多个,那么默认打印第一个
# base 打印所有当前继承的父类
​
print(Student.__base__)     # 只继承了一个父类,只能查看到一个父类
print(Teacher.__base__)     # 虽然继承了两个父类,但也只能查看到从左往右第一个父类
​
print(Student.__bases__)    # 只继承了一个父类,可以查看所有继承的父类
print(Teacher.__bases__)    # 继承了两个父类,也可以查看所有继承的父类

【七】经典类和新式类

# 经典类和新式类的区别在于Python版本的不同
# 在 py3 版本之前存在两个概念 ,在之后就没有经典类的概念了,只有新式类
# 【一】什么是经典类
# 在py2中没有显示继承 object 的类或者是该类的子类都是经典类
# 【二】什么是新式类
# 在py2中显示继承 object 的类或者是该类的子类都是新式类
# 在py3之后所有的类默认都是新式类,不写m默认继承 object

【八】继承和抽象

  • 继承是由少变多

  • 抽象是由多变少

# 【1】没有继承和抽象
class Cat(object):def speak(self):print(f"喵喵叫")
​def eat(self):print(f"猫可以吃饭")
​def drink(self):print(f"猫可以喝水")
​
​
class Dog(object):def speak(self):print(f"汪汪叫")
​def eat(self):print(f"狗可以吃饭")
​def drink(self):print(f"狗可以喝水")
​
​
cat_one = Cat()
print(cat_one.speak())
dog_one = Dog()
print(dog_one.speak())
# 【使用抽象和继承】# 先抽象
class Animal(object):def speak(self):print(f"{self.name}可以叫")def eat(self):print(f"{self.name}可以吃饭")def drink(self):print(f"{self.name}可以喝水")
​# 再继承
class Cat(Animal):def __init__(self,name):self.name = '猫'+name
​
class Dog(Animal):def __init__(self,name):self.name = '狗'+name
​
cat_one = Cat(name='小花')
print(cat_one.speak())          # 猫小花可以叫
dog_one = Dog(name='小黑')
print(dog_one.eat())            # 狗小黑可以吃饭

【九】不封装与封装的属性查找顺序

  • 无封装时继承(通过谁实例化得到的对象就优先去谁里面找)

class Foo:def f1(self):print('Foo.f1')
​# 【四】在父类 Foo 里面找到了 f2def f2(self):# 【五】打印 Foo.f2print('Foo.f2')# 【六】self.f1self.f1()
​
​
class Bar(Foo):# 【七】因为是 通过Bar实例化得到的对象,所以 self 就是 Bardef f1(self):# 【八】打印 Bar.f1print('Bar.f1')# 【三】Bar里面没有f2,去父类找 Foo
​
​
# 【一】类实例化得到对象
b = Bar()
# 【二】对象调用方法 f2
b.f2()
# Foo.f2
# Bar.f1
  • 有封装时继承(变形之后,就只能在当前自己的类中找)

class Foo:def __f1(self):print('Foo.f1')# 【四】在父类 Foo 里面找到了 f2def f2(self):# 【五】打印 Foo.f2print('Foo.f2')# 【六】self.__f1# 没有变形时self 是谁就去谁里面找# 变形之后,就只能在当前自己的类中找self.__f1()class Bar(Foo):def __f1(self):# 【八】打印 Bar.f1print('Bar.f1')# 【三】Bar里面没有f2,去父类找 Foo# 【一】类实例化得到对象
b = Bar()
# 【二】对象调用方法 f2
b.f2()
# Foo.f2
# Foo.f1
【小总结】
  • 如果属性不封的情况下,谁实例化得到的self 就去谁里面找

  • 如果属性封装的情况下 ,谁实例化得到的self 无效,只能在当前所在的类的名称空间里面找

【十】菱形结构继承顺序

  • 在py2中分为深度优先和广度优先

  • 在py3中只有广度优先

【1】深度优先
  • 深度优先发生在经典类上,当前类内部找不到指定属性时,会向上找

  • 一条线找到黑

【2】广度优先
  • 广度优先发生在新式类上,在当前类内部找不到指定属性时,会向上找

  • 顺序是广度优先

class A(object):def test(self):print('from A')class B(A):def test(self):print('from B')class C(A):def test(self):print('from C')class D(B):def test(self):print('from D')class E(C):def test(self):print('from E')class F(D, E):# def test(self):#     print('from F')passf1 = F()
f1.test()# 新式类继承顺序:F->D->B->E->C->A
# 经典类继承顺序:F->D->B->A->E->C
  • 只有新式才有这个属性可以查看线性列表,经典类没有这个属性

print(F.__mro__)

【十一】派生

  • 派生是指,子类继承父类,派生出自己的属性与方法,并且重用父类的属性与方法

【1】子类继承父类的属性
class People:school = '北大'def __init__(self,name,sex,age):self.name = nameself.sex = sexself.age = ageclass Teacher(People):# 派生:派生出自己新的属性,在进行属性查找时,子类的属性会优先于父类被查找到def __init__(self,name,sex,age,title):self.name = nameself.sex = sexself.age = ageself.title = titledef teach(self):print('%s is teaching' % self.name)
#
# 只会找自己类中的__init__,并不会自动调用父类中的
obj = Teacher('knight','male',18,'教授')
print(obj.teach(),obj.name,obj.sex,obj.age,obj.title,)
# knight is teaching
# None
# knight male 18 教授
【2】继承方式一
class People:school = '清华大学'def __init__(self, name, sex, age):self.name = nameself.sex = sexself.age = ageclass Teacher(People):# 派生:派生出自己新的属性,在进行属性查找时,子类的属性会优先于父类被查找到def __init__(self,name,sex,age,title):# 直接调用 父类 中 的 __init__ 方法# 调用的是函数,因而需要传入selfPeople.__init__(self,name,sex,age)self.title = titledef teach(self):print('%s is teaching' % self.name)# 只会找自己类中的__init__,并不会自动调用父类的
obj = Teacher('knight','male',18,'叫兽')
print(obj.name,obj.sex,obj.age,obj.title)
【3】继承方式二
# 调用super()会得到一个特殊的对象
# 该对象专门用来引用父类的属性
# 且严格按照MRO规定的顺序向后查找
class People:school = '清华大学'def __init__(self, name, sex, age):self.name = nameself.sex = sexself.age = ageclass Teacher(People):# 派生 : 派生出自己新的属性,在进行属性查找时,子类中的属性名会优先于父类被查找def __init__(self, name, sex, age, title):# 直接调用 父类 中 的 __init__ 方法# 调用的是绑定方法,因此会自动传入self,但是需要传入相应的参数super().__init__(name, sex, age)self.title = titledef teach(self):print('% is teaching' % self.name)# 只会找自己类中的__init__,并不会自动调用父类的
obj = Teacher('knight', 'male', 18, '叫兽')print(obj.name, obj.sex, obj.age, obj.title)

【十二】组合

在一个类中,以另外一个类的对象作为数据属性,称为类的组合

class Course:def __init__(self, name, period, price):self.name = nameself.period = periodself.price = pricedef tell_info(self):print(f'当前课程名字 {self.name} 当前课程周期 {self.period} 当前课程价格 {self.price}')class Date:def __init__(self, year, mon, day):self.year = yearself.mon = monself.day = daydef tell_birth(self):print(f'当前生日 {self.year} 年 {self.mon} 月 {self.day} 日')class People:school = '清华大学'def __init__(self, name, sex, age,title):self.name = nameself.sex = sexself.age = ageself.title = titledef tell_school_info(self):print(f"{self.name}在{self.school}工作")# Teacher类基于继承来重用People代码
# 基于组合来重用Date类和Course类的代码
class Teacher(People):def __init__(self, name, sex, age, title, year, mon, day):super().__init__(name, age, sex,title)# 老师有生日self.birth = Date(year, mon, day)# 老师有课程,可以在实例化后,往该列表添加Course类的对象self.courses = []def teach(self):print(f"老师正在授课{self.name},目前是{self.title}")python = Course('python', '3mons', 3000)
linux = Course('linux', '2mons', 2000)
teacher1 = Teacher('knight', 'male', 18, 'NB', 2002, 6, 3)# teacher1有两门课程
teacher1.courses.append(python)
teacher1.courses.append(linux)# 重用Data类的功能
teacher1.birth.tell_birth()
teacher1.tell_school_info()
teacher1.teach()
# 重用Course类的功能
for obj in teacher1.courses:obj.tell_info()# 当前生日 2002 年 6 月 3 日
# knight在清华大学工作
# 老师正在授课knight,目前是NB
# 当前课程名字 python 当前课程周期 3mons 当前课程价格 3000
# 当前课程名字 linux 当前课程周期 2mons 当前课程价格 2000

【十三】组合与继承的区别

  • 组合与继承都是有效地利用已有类的资源的重要方式。但是二者的概念和使用场景皆不同

【1】继承的方式
  • 通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物

  • 当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如老师是人,学生是人

【2】组合的方式
  • 用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python和linux课程,教授有学生s1、s2、s3..

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring与AI结合-spring boot3整合AI组件

⛰️个人主页: 蒾酒 🔥系列专栏:《spring boot实战》 目录 写在前面 spring ai简介 单独整合al接口 整合Spring AI组件 起步条件 ​编辑 进行必要配置 写在最后 写在前面 本文介绍了springboot开发后端服务中,AI组件(Spring A…

软件工程案例学习-图书管理系统-面向对象方法

文档编号:LMS_1 版 本 号:V1.0 ** ** ** ** ** ** 文档名称:需求分析规格说明书 项目名称:图书管理系统 项目负责人:计敏 胡杰 ** ** …

使用Docker安装MySql数据库

大家好,今天给大家分享一下如何使用docker安装MySql数据库,关于docker的安装和常用命令,大家可以参考下面两篇文章,本文中不做过多描述。 Docker在Windows与CentOS上的安装 Docker常用命令 一、拉取MySql数据库镜像 docker pul…

IIS部署vue项目 IIS重写URL

【第一步】安装IIS {1)打开控制面板 -> 打开程序和功能 -> 打开启用或关闭windows功能 (2)找到 Internet Information Services 勾选【web管理工具】和【万维网服务】,然后 确定 【第二步】安装URL重写模块 1). 安装URL …

2.开始学习C++

开始学习C 写在前面创建C程序1.输入输出2.main()函数3.头文件4.名称空间 C其他语句1.cin2.类3.函数4.自定义函数 写在前面 每次写读书笔记之前我都打算先写一会自己的心得,或者一些前情提要。先说说为什么要写这个读书心得吧。 首先是自己摆烂太久了,从…

C++ | Leetcode C++题解之第73题矩阵置零

题目&#xff1a; 题解&#xff1a; class Solution { public:void setZeroes(vector<vector<int>>& matrix) {int m matrix.size();int n matrix[0].size();int flag_col0 false;for (int i 0; i < m; i) {if (!matrix[i][0]) {flag_col0 true;}for …

【笔试训练】day20

1.经此一役小红所向无敌 默认小红血量无限。直接计算出经过几轮攻击后&#xff0c;会出现人员伤亡。 对于对立来说他最多承受n轮光的攻击&#xff0c;对于光来说&#xff0c;他最多承受立得m轮攻击。 所以在经过min(n,m)轮回合之后&#xff0c;他们两个人至少死一个。活下来的…

html实现网页插入音频

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文主要介绍html中 如何插入音乐和视频 视频插入 标签:<video></video> 兼容格式:mp4,因为别的浏览器都有不兼容的格式&#xff0c;唯一对mp4全都兼容。所以尽量使用mp4格式。 属性: 属性属性值…

深度学习学习日记(5.6)

在 ViT&#xff08;Vision Transformer&#xff09;模型中&#xff0c;输入图像被分割成固定大小的图块&#xff0c;然后通过一个线性变换&#xff08;通常是一个卷积层&#xff09;来将每个图块投影到一个较低维度的特征空间。这些投影后的图块被视为序列&#xff0c;然后输入…

【linux软件基础知识】-kobject结构

设备驱动模型中的一个基本结构kobject kobject结构是Linux内核设备驱动模型中的一个基本结构。设备驱动模型中的各种对象其内部都会包含一个kobject ,地位相当于面向对象思想中的总基类, 它充当设备驱动程序模型中各种对象的公共基础,并为这些对象提供基本功能。 以下是有…

MATLAB算法实战应用案例精讲-【数模应用】正态性检验(附R语言代码实现)

目录 前言 几个高频面试题目 正态性检验的几个知识点 知识储备

解决Win10家庭版找不到组策略gpedit.msc的·方法

因为电脑出问题&#xff0c;一开机就会自动开启ie浏览器&#xff0c;所以就想找有没有方法解决&#xff0c;然后就了解到了gpedit.msc的作用以及相关的一些方法&#xff0c;也是为之后也许有人遇到相同的问题有个提供方法的途径。 首先我们直接运行gpedit.msc 是找不到的&…

【Qt QML】QLibrary加载共享库中的类

QLibrary是一个用于加载动态链接库&#xff08;或称为共享库&#xff09;的类。它提供了一种独立于平台的方式来访问库中的功能。 在QLibrary中&#xff0c;可以通过构造函数或setFileName()方法设置要加载的库文件名。当加载库文件时&#xff0c;QLibrary会搜索所有平台特定的…

计算机网络【应用层】邮件和DNS

文章目录 电子邮件DNSDNS提供的服务&#xff1a;域名分级域名解析流程DNS资源记录DNS服务器类型 电子邮件 使用SMTP协议发送邮件之前&#xff0c;需要将二进制多媒体数据编码为ASCII码SMTP一般不使用中间邮件服务器发送邮件&#xff0c;如果收件服务器没开机&#xff0c;那么会…

【iOS】多线程

文章目录 前言一、多线程的选择方案二、GCD和NSOperation的比较二、多线程相关概念任务队列 三、死锁情况主队列加同步任务 四、任务队列组合主队列异步并发队列异步 前言 这两天将iOS的多线程的使用都看了一遍&#xff0c;iOS的多线程方案有许多&#xff0c;本篇博客主要总结…

流畅的python-学习笔记_符合python风格的对象

对象表示形式 查看对象说明&#xff0c;可以通过__repr__和__str__方法&#xff0c;前者主要用于开发者&#xff0c;后者主要用于用户&#xff0c;这两个方法分别对内置函数repr和str函数提供支持 向量类 备选构造方法 classmethod和staticmethod staticmethod用的不是特别…

算法提高之股票买卖 V

算法提高之股票买卖 V 核心思想&#xff1a;状态机 一共有三种情况 &#xff1a; 空仓&#xff0c;持仓&#xff0c;冻结期f[i,j]表示第i天的状态j状态计算&#xff1a; 如下 #include <iostream>#include <cstring>#include <algorithm>using namespace …

基于鸢尾花数据集的四种聚类算法(kmeans,层次聚类,DBSCAN,FCM)和学习向量量化对比

基于鸢尾花数据集的四种聚类算法&#xff08;kmeans&#xff0c;层次聚类&#xff0c;DBSCAN,FCM&#xff09;和学习向量量化对比 注&#xff1a;下面的代码可能需要做一点参数调整&#xff0c;才得到所有我的运行结果。 kmeans算法&#xff1a; import matplotlib.pyplot a…

音视频开发3 视频基础,图片基础

图片像素&#xff08;Pixel&#xff09; 一张图片是由多少个 像素 构成的。 例如一张图片是由60x50组成的。 位深度 bit depth RGB表示法 红&#xff08;Red&#xff09;、绿&#xff08;Green&#xff09;、蓝&#xff08;Blue&#xff09; 除了24bit&#xff0c;常见的位深…

electron 通信总结

默认开启上下文隔离的情况下 渲染进程调用主进程方法&#xff1a; 主进程 在 main.js 中&#xff0c; 使用 ipcMain.handle&#xff0c;添加要处理的主进程方法 const { ipcMain } require("electron"); 在 electron 中创建 preload.ts 文件&#xff0c;从 ele…