Python开发基础-Day18继承派生、组合、接口和抽象类

时间:2021-10-06 22:32:52

类的继承与派生

经典类和新式类

在python3中,所有类默认继承object,但凡是继承了object类的子类,以及该子类的子类,都称为新式类(在python3中所有的类都是新式类)

没有继承object类的子类成为经典类(在python2中,没有继承object的类,以及它的子类,都是经典类)

 class People:
pass
class Animal:
pass
class Student(People,Animal): #People、Animal称为基类或父类,Student为子类,Student继承了People和Animal的所有属性
pass
print(Student.__bases__) #__bases__方法,查看继承的类的元组
print(People.__bases__)
print(Animal.__bases__)

输出结果:

 (<class '__main__.People'>, <class '__main__.Animal'>)    #继承了两个父类
(<class 'object'>,) #默认继承了object类
(<class 'object'>,)

继承

继承是为了减少代码重用的问题,以减少代码冗余。

继承是一种是什么是什么的关系,例如老师类是人类,而非老师类是生日类

继承类示例:

 class People:    #定义父类People
def __init__(self, name, age):
self.name = name
self.age = age
def walk(self):
print('%s is walking' %self.name) #Teacher类和Student类无任何属性
class Teacher(People): #Teacher类继承People类的属性
pass
class Student(People): #Student类继承People类的属性
pass

引用测试:

 t=Teacher('bob',18)    #实例化一个Teacher对象,而非People对象,Student子类同理
print(type(t))
print(t.name,t.age)
print(t.__dict__)
t.walk() #Teacher子类继承了People的属性,使得Teacher子类的对象能够调用到父类的属性 输出结果:
<class '__main__.Teacher'>
bob 18
{'name': 'bob', 'age': 18}
bob is walking

派生

派生是在子类继承父类的基础上, 定义子类独有的属性,例如Teacher可以有教师等级的划分、有教学课程的划分,但是继承父类People类是没有等级和课程的划分的。

示例:

 #定义父类People
class People:
def __init__(self, name, age,sex):
self.name = name
self.age = age
self.sex=sex
def walk(self):
print('%s is walking' % self.name)
def test(self):
print('test class from father class %s' %self.name)
#定义Teacher子类
class Teacher(People):
school = 'jialidun'
def __init__(self, name, age,sex,level,salary):
People.__init__(self,name,age,sex) #继承父类的初始化内容,实例化时候接收的参数name、age、sex会传给People.__init__
self.level=level #派生的独有属性
self.salary=salary #派生的独有属性
def teach(self): #派生的独有属性
print('%s is teaching' %self.name)
def test(self): #派生父类的已有属性,对象在进行属性引用的时候会优先引用实例化过程中用到的类
People.test(self)
print('from teacher')
#定义Student子类
class Student(People):
def __init__(self, name, age,sex,group):
People.__init__(self, name, age, sex)
self.group=group
def study(self):
print('%s is studying' %self.name)

测试验证:

 t=Teacher('natasha',18,'male',10,3000) #__init__(t,'natasha',18,'male',10,3000)
print(Teacher.__bases__)
print(Teacher.__dict__)
t.test()

组合

不同于继承,组合是包含的意思,表示一种什么有什么的关系,也是为了减少重复代码的

示例:还是People、Teacher和Student的例子,只是加上了一个Birthday生日类

 #Birthday类,需要传入年月日
class Birthday:
def __init__(self,year,mon,day):
self.year=year
self.mon=mon
self.day=day
def tell_birth(self):
print('出生于<%s>年 <%s>月 <%s>日' % (self.year,self.mon,self.day))
#People类,需要接受名字年龄年月日,年月日传给Birthday类
class People:
def __init__(self, name, age, year, mon, day):
self.name = name
self.age = age
#__init__接收的year, mon, day传给Birthday类
self.birth = Birthday(year, mon, day) #包含Birthday类,生日不只是人类才有,其他动物也可以有生日,不同于继承
def walk(self):
print('%s is walking' % self.name)
#Teacher类
class Teacher(People):
def __init__(self, name, age, year, mon, day,level,salary):
#__init__接收的name, age, year, mon, day传给People类
People.__init__(self,name,age,year,mon,day)
self.level=level
self.salary=salary
def teach(self):
print('%s is teaching' %self.name)
#Student类
class Student(People):
def __init__(self, name, age, year, mon, day,group):
People.__init__(self,name,age,year,mon,day)
self.group=group
def study(self):
print('%s is studying' %self.name)

测试验证:

 t=Teacher('hurry',18,1990,2,33,10,3000)    #传入的值为Teacher类接收的值
print(t.name,t.age) #对象t的名字和年龄
print(t.birth) #输出的是一个类对象,因为父类People定义的birth属性就是一个类Birthday
t.birth.tell_birth() #查看对象t所继承的People类的birth属性(Birthday类)的tell_birth()属性
print(t.birth.year)
print(t.birth.mon)
print(t.birth.day)

接口和抽象类

接口

接口是一组功能的入口,要调用某一组功能,需要通过接口来进行调用,而不需要关注这组功能是如何实现的,要的只是结果。

在类里,接口是提取了一群类共同的函数,可以把接口当做一个函数的集合。

python模仿接口示例:

 #模仿Linux内文件读写的接口,Linux不管是文本,还是磁盘还是进程都是通过文件去实现的,只不过方法不同,但是没关系
class File: #定义一个接口类,提供read和write方法,但是一定是pass没有处理过程的,因为功能的实现具体靠的是子类
def read(self): #定接口函数read
pass
def write(self): #定义接口函数write
pass
#定义子类实现读写功能
#文本文件的读写
class Txt(File): #文本,具体实现read和write
def du(self): #注意并不是read
print('文本数据的读取方法')
def xie(self): #注意并不是write
print('文本数据的写入方法')
#硬盘数据的读写
class Sata(File): #磁盘,具体实现read和write
def read(self):
print('硬盘数据的读取方法')
def write(self):
print('硬盘数据的写入方法')
#进程数据的读写
class Process(File):
def read(self):
print('进程数据的读取方法')
def write(self):
print('进程数据的写入方法')

测试验证:硬盘和进程一样,所以制作文本和硬盘的测试即可

硬盘读写测试:

 disk=Sata()    #实例化一个硬盘读写对象
disk.read() #硬盘读
disk.write() #硬盘写 输出结果:
硬盘数据的读取方法
硬盘数据的写入方法

文本读写测试:执行后会发现没有任何输出,那是因为txt对象实际*问的read和write属性并非子类Txt所提供的属性,Txt所提供的属性只是du和xie,但是txt对象有read和write属性,别忘了Txt类是继承了父类File的属性,所以实际上txt对象的read和write属性是父类File提供的

 txt=Txt()
txt.read()
txt.write()

正确的做法是将Txt类的du和xie方法改成read和write方法,这么做的意义为归一化

归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。

抽象类

抽象类的本质上也是类,但是抽象类只能够被继承,不能进行实例化,也就是说可以当父类,但是不能生成对象。

抽象类介于接口和归一化中间,用于实现接口的归一化

当子类继承抽象类的时候,如果抽象类定义了抽象方法,那么子类必须要定义同名的方法。即父类限制:

  1、子类必须要有父类的方法

  2、子类实现的方法必须跟父类的方法的名字一样

python的抽象类通过abc模块实现。

接口归一化示例:

 import abc
class File(metaclass=abc.ABCMeta): #metaclass指的是元类,边会讲,现在只需记住这个词
@abc.abstractmethod #抽象方法,即一个装饰器装饰read属性
def read(self):
pass
@abc.abstractmethod #抽象方法,即一个装饰器装饰write属性
def write(self):
pass
# # 当继承File类时候,如果没有read和write方法,会提示出错TypeError: Can't instantiate abstract class Txt with abstract methods read, write
# class Txt(File):
# def du(self):
# print('文本数据的读取方法')
# def xie(self):
# print('文本数据的写入方法')
#定义子类具体实现文本的读写操作
class Txt(File):
def read(self):
print('文本数据的读取方法')
def write(self):
print('文本数据的写入方法')
#定义子类具体实现硬盘的读写操作
class Sata(File):
def read(self):
print('硬盘数据的读取方法')
def write(self):
print('硬盘数据的写入方法')
#定义子类具体实现进程的读写操作
class Process(File):
def read(self):
print('进程数据的读取方法')
def write(self):
print('进程数据的写入方法')

测试验证:

 t=Txt()
t.read()
t.write()
s=Sata()
s.read()
s.write()
输出结果:
文本数据的读取方法
文本数据的写入方法
硬盘数据的读取方法
硬盘数据的写入方法

Python开发基础-Day18继承派生、组合、接口和抽象类的更多相关文章

  1. Python开发基础-Day19继承组合应用、对象序列化和反序列化,选课系统综合示例

    继承+组合应用示例 class Date: #定义时间类,包含姓名.年.月.日,用于返回生日 def __init__(self,name,year,mon,day): self.name = nam ...

  2. Python开发基础-Day20继承实现原理、子类调用父类的方法、封装

    继承实现原理 python中的类可以同时继承多个父类,继承的顺序有两种:深度优先和广度优先. 一般来讲,经典类在多继承的情况下会按照深度优先的方式查找,新式类会按照广度优先的方式查找 示例解析: 没有 ...

  3. python基础之继承派生、组合、接口和抽象类

    类的继承与派生 经典类和新式类 在python3中,所有类默认继承object,但凡是继承了object类的子类,以及该子类的子类,都称为新式类(在python3中所有的类都是新式类) 没有继承obj ...

  4. Py修行路 python基础 (十五)面向对象编程 继承 组合 接口和抽象类

    一.前提回忆: 1.类是用来描述某一类的事物,类的对象就是这一类事物中的一个个体.是事物就要有属性,属性分为 1:数据属性:就是变量 2:函数属性:就是函数,在面向对象里通常称为方法 注意:类和对象均 ...

  5. python面向对象编程 继承 组合 接口和抽象类

    1.类是用来描述某一类的事物,类的对象就是这一类事物中的一个个体.是事物就要有属性,属性分为 1:数据属性:就是变量 2:函数属性:就是函数,在面向对象里通常称为方法 注意:类和对象均用点来访问自己的 ...

  6. Python 继承和组合 接口

    #解决代码重用的问题,减少代码冗余 #继承是一种什么'是'什么的关系 class People: def __init__(self, name, age): # print('People.__in ...

  7. Python设计模式 - 基础 - 封装 &amp&semi; 继承 &amp&semi; 多态

    面向对象的核心是对象,世间万物都可以看作对象,任何一个对象都可以通过一系列属性和行为来描述,可以包含任意数量和类型的数据或操作.类是用来描述具有相同属性和方法的所有对象的集合.类通常是抽象化的概念,而 ...

  8. JAVA基础之——三大特征、接口和抽象类区别、重载和重写区别、&equals;&equals;和equals区别、JAVA自动装箱和拆箱

    1 java三大特征 1)封装:即class,把一类实体定义成类,该类有变量和方法. 2)继承:从已有的父类中派生出子类,子类实现父类的抽象方法. 3)多态:通过父类对象可以引用不同的子类,从而实现不 ...

  9. 慢慢人生路,学点Jakarta基础-深入剖析Java的接口和抽象类

    在java面向对象编程的,抽象类和接口始终存在有疑问的地方,因为两者太多相似有太多不同,在刚开始学习的时候经常弄的不对,使用情景搞混,今天来总结之前学习Java中接口和抽象类的问题. 抽象类 了解:只 ...

随机推荐

  1. JQ AJAX

    用AJAX方法不刷新网页使用下拉列表连接数据库 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ...

  2. java操作MySQL数据事务的简单学习

    在执行数据更改操作前使用数据库连接对象调用setAutoCommit方法(conn.setAutoCommit(false)),其参数true或false区别: true:sql命令的提交(commi ...

  3. Codeforces Round &num;284 &lpar;Div&period; 2&rpar;

    题目链接:http://codeforces.com/contest/499 A. Watching a movie You have decided to watch the best moment ...

  4. (11)nehe教程5---3D空间

    3D空间: 我们使用多边形和四边形创建3D物体,在这一课里,我们把三角形变为立体的金子塔形状,把四边形变为立方体. 在上节课的内容上作些扩展,我们现在开始生成真正的3D对象,而不是象前两节课中那样3D ...

  5. 4&period;I&sol;O复用以及基于I&sol;O复用的回射客户端&sol;服务器

    I/O复用:当一个或多个I/O条件满足时,我们就被通知到,这种能力被称为I/O复用. 1.I/O复用的相关系统调用 posix的实现提供了select.poll.epoll两类系统调用以及相关的函数来 ...

  6. Form&period;Close跟Form&period;Dispose

    关于Form.Close跟Form.Dispose   我们在Winform开发的时候,使用From.Show来显示窗口,使用Form.Close来关闭窗口.熟悉Winform开发的想必对这些非常熟悉 ...

  7. 玩转Node&period;js单元测试

    代码部署之前,进行一定的单元测试是十分必要的,这样能够有效并且持续保证代码质量.而实践表明,高质量的单元测试还可以帮助我们完善自己的代码.这篇博客将通过一些简单的测试案例,介绍几款Node.js测试模 ...

  8. Linux的启动流程 (二)

    引:本文以RedHat9.0和i386平台为例,剖析了从用户打开电源直到屏幕出现命令行提示符的整个Linux启动过程.并且介绍了启动中涉及到的各种文件.阅读Linux源代码,无疑是深入学习Linux的 ...

  9. R--线性回归诊断(一)

    线性回归诊断--R [转载时请注明来源]:http://www.cnblogs.com/runner-ljt/ Ljt   勿忘初心  无畏未来 作为一个初学者,水平有限,欢迎交流指正. 在R中线性回 ...

  10. ssh 连接失败 sz rz 安装

    sz 下载命令, rz上传命令的安装 sudo apt-get install lrzsz 1. 检查sshd服务的状态以及端口是否正常, 如下为正常状态 sudo netstat -nlp | gr ...