类的继承和派生

news/发布时间2024/5/19 14:03:09

【一】继承介绍

# 面向对线三大特性:继承 封装 多态
# 继承# 【一】什么是继承
# 继承就是一种创建新类的方式,新建的类可以继承一个或多个类的属性。
# 新的类如果有自己的属性,那就叫派生# 【二】继承的优点
# 可以继承父类的所有属性和方法,实现代码的去重# 【三】继承方式
# 单继承:继承一个父类的子类
# 多继承:继承多个父类的子类# class Student(School):
# 继承的类叫父类 School
# 新建的类叫子类 Studentclass Person(object):height = 180weight = 50class School(object):school = "清华"# 【1】单继承:只继承一个父类
class Student(Person):def __init__(self, name):self.name = namedef tell_me(self):print(f"我是 {self.name} 我身高 {self.height} 体重 {self.weight}")stu1 = Student("dream")
stu1.tell_me()# 【2】多继承:继承两个以上的父类
class Teacher(School, Person):def __init__(self, name):self.name = namedef tell_me(self):print(f"我是 {self.name} 我身高 {self.height} 体重 {self.weight} 学校在 {self.school}")teacher = Teacher("opp")
teacher.tell_me()# 【3】如何查看继承的父类
# (1)查看当前继承的父类 __base__ : 如果继承多个父类,默认只打印第一个继承的父类
print(Student.__base__)  # <class '__main__.Person'>
print(Teacher.__base__)  # <class '__main__.Person'>
# (2)查看当前继承的父类们 : __bases__ 一个元组,元组中放的是所有继承的父类
print(Student.__bases__)  # (<class '__main__.Person'>,)
print(Teacher.__bases__)  # (<class '__main__.Person'>, <class '__main__.School'>)

【二】经典类和新式类

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

【三】继承和抽象

# 什么是继承和抽象
# 继承是子类和父类之间的关系,什么是什么的概念
# 抽象相当于将某部分抽立起来再总结# 【一】抽象
# 将不同的类。根据指定的表征总结起来归介于一个类
# 猫和狗 --> 动物
# 猪八戒 麦兜 ---> 猪
# 梅西 奥巴马 --> 人
# 猪 和 人 ---> 动物# 【二】继承
# 基于抽象的结果,然后用语言去实现# 【三】继承和抽象
# 继承是由少变多
# 抽象是由多变少# 【四】在python中实现继承
# 【1】没有继承和抽象
# 有一只猫
class Cat(object):def speak(self):print(f"猫可以喵喵叫")def eat(self):print("猫可以吃饭")def drink(self):print("猫可以喝水")# 有一只狗
class Dog(object):def speak(self):print(f"狗可以旺旺叫")def eat(self):print("狗可以吃饭")def drink(self):print("狗可以喝水")# 【2】抽象
# 总结起来一个公共的类,可以吃喝拉撒睡
class Animal(object):def speak(self):print(f"{self.name}可以叫")def eat(self):print(f"{self.name}可以吃饭")def drink(self):print(f"{self.name}可以喝水")# 【3】继承
# 有一只猫
class Cat(Animal):def __init__(self, name):self.name = '猫'+name# 有一只狗
class Dog(Animal):def __init__(self, name):self.name = '狗'+namecat_one = Cat(name='小花')
print(cat_one.speak())
dog_one = Dog(name="旺财")
print(dog_one.speak())

【四】封装后继承的属性查找顺序

【1】封装之前的属性查找顺序

class Foo:def f1(self):print('Foo.f1')# 【四】在父类 Foo 里面找到了 f2def f2(self):# 【五】打印 Foo.f2print('Foo.f2')# 【六】self.f1 ---> self 是谁 ?# 触发的是 Foo.f1 还是 Bar.f1?# Foo.f1 3# Bar.f1 2self.f1()class Bar(Foo):# 【七】因为是 通过Bar实例化得到的对象,所以 self 就是 Bardef f1(self):# 【八】打印 Bar.f1print('Bar.f1')# 【三】Bar里面没有f2,去父类找 Foo# 【一】类实例化得到对象
b = Bar()
# 【二】对象调用方法 f2
b.f2()
class B(object):def read(self):print(self)class A(B):...a = A()
a.read()b = B()
b.read()# 哪个对象调用方法,self 就是谁

【2】有封装的时候的继承

class Foo:# __f1 --> _Foo__f1def __f1(self):print('Foo.f1')# 【4】在Foo里面找到了 f2def f2(self):# 【5】打印 Foo.f2print('Foo.f2')# 【6】# 没有变形的时候 self 是谁就去谁里面找# 但是变形之后 就只能在自己的类里面找,没办跳到别的类里面# Foo.f1 2# Bar.f1 3self.__f1()class Bar(Foo):# 【3】没有f2. 去 Foodef __f1(self):print('Bar.f1')# 【1】
b = Bar()
# 【2】
b.f2()

【3】总结

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

【五】派生

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

【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('dream', 'male', 18, '高级讲师')print(obj.name, obj.sex, obj.age, obj.title)
# dream 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, age, sex)self.title = titledef teach(self):print('%s is teaching' % self.name)# 只会找自己类中的__init__,并不会自动调用父类的
obj = Teacher('dream', 'male', 18, '高级讲师')print(obj.name, obj.sex, obj.age, obj.title)
# dream male 18 高级讲师

【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('%s is teaching' % self.name)# 只会找自己类中的__init__,并不会自动调用父类的
obj = Teacher('dream', 'male', 18, '高级讲师')print(obj.name, obj.sex, obj.age, obj.title)
# dream male 18 高级讲师

【六】组合

# 在一个类中以另外一个类的对象作为数据属性,称为类的组合。
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):self.name = nameself.sex = sexself.age = age# Teacher类基于继承来重用People的代码
# 基于组合来重用Date类和Course类的代码
class Teacher(People):# 老师是人def __init__(self, name, sex, age, title, year, mon, day):super().__init__(name, age, sex)# 老师有生日self.birth = Date(year, mon, day)# 老师有课程,可以在实例化后,往该列表中添加Course类的对象self.courses = []def teach(self):print(f'当前老师正在授课 {self.name}')python = Course('python', '3mons', 3000.0)
linux = Course('linux', '5mons', 5000.0)
teacher1 = Teacher('dream', 'male', 18, '金牌讲师', 1987, 3, 23)# teacher1有两门课程
teacher1.courses.append(python)
teacher1.courses.append(linux)# 重用Date类的功能
teacher1.birth.tell_birth()# 重用Course类的功能
for obj in teacher1.courses:obj.tell_info()# 当前生日 1987 年 3 月 23 日
# 当前课程名字 python 当前课程周期 3mons 当前课程价格 3000.0
# 当前课程名字 linux 当前课程周期 5mons 当前课程价格 5000.0

【六】组合和继承的区别

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

【1】继承的方式

  • 通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物。
  • 当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如老师是人,学生是人

【2】组合的方式

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

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

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

相关文章

SQL

-一、名词 DB(DataBase):数据库 DBMS(DataBase Management System):数据库管理系统 SQL(Structured Query Language):一种操作关系型数据库的编程语言 二、安装: https://dev.mysql.com/downloads/windows/installer/8.0.html 选择MySQL Community Downloads -> M…

2024 年 5 月 5 日 周日 晴 常(245 字)

正文今天值班,但是睡到 9:30 才醒。副行长在我睡觉的时候打电话,说他有事待会儿来。我一听这话,肯定就不会来了,果然不出所料(笑。下午 16:00 早退,反正值班没人管,17:00 有点困,便睡了一觉。以为最多睡到 18:30,结果睡到了 19:30……弄好了灵送的绿植和透明板。研究了…

Plumed分子模拟后分析

Plumed是一个强大的分子模拟数据处理工具,可以在模拟的过程中逐步分析,也可以保存模拟的轨迹做后分析。本文紧接前面的“增强采样软件PLUMED的安装与使用”文章,还有“直方图与核密度估计”文章。介绍了如何使用Plumed后分析工具,对输出的反应坐标的轨迹进行核密度估计。技…

ubuntu 桥接模式无法上网解决

ubuntu安装,根据个人的选择来配置网络信息,以下是vmare配置桥接模式时ubuntu无法上网的处理方式: 1. vmare-》虚拟机-》设置, 选中桥接模式(复制物理状态可以不勾选)2. vmare-》编辑-》虚拟网络编辑器, 选中更改设置 2. 选中VMnet0网卡,该网卡选中电脑目前在用的网卡名…

经验之谈:我为什么选择了这样一个激进的缓存大Key治理方案

本文将结合我的一次Redis大Key的治理经验,来浅谈一下缓存大Key的治理方案选择。文中主要包括缓存大Key基础知识、大Key治理方案选择、大Key治理案例等,适合有一定开发经验的开发者阅读,希望对大家有帮助。一、引言 本文将结合我的一次Redis大Key的治理经验,来浅谈一下缓存大…

[转帖]长连接黑洞重现和分析

https://plantegg.github.io/2024/05/05/%E9%95%BF%E8%BF%9E%E6%8E%A5%E9%BB%91%E6%B4%9E%E9%87%8D%E7%8E%B0%E5%92%8C%E5%88%86%E6%9E%90/ 长连接黑洞重现和分析 这是一个存在多年,遍及各个不同的业务又反反复复地在集团内部出现的一个问题,本文先通过重现展示这个问题,然后…