Python基础53:面向对象三大特性--继承
2021/6/21 1:26:13
本文主要是介绍Python基础53:面向对象三大特性--继承,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
# ************************************************************************** # Python学习 # ************************************************************************** # ** 所属主题: 类 # ** 所属分层: 05 面向对象三大特性--继承 # ** 功能描述: 05 面向对象三大特性--继承 # ** 创 建 者: 陈红伟 # ** 创建日期: 2021/6/19 5:53 下午 # ************************************************************************** # ** 修改日期 修改人 修改内容 # ** 2021/6/19 陈红伟 新增学习内容代码 # ************************************************************************** """ 本章内容: 继承: 单继承,多继承,__bases__(查看类继承关系) , __dict__(查看对象中的属性), 经典类,新式类,派生(重写),菱形继承,深度优先查找,广度优先查找,mro(),Mixins机制 """ """ 一、什么是继承 1、继承是一种创建新类的方式,新建的子类可称之为子类或者派生类,父类又可以称之为基类或超类,子类会遗传父类的属性 2、需要注意的是python支持多继承 在python中,新建的类可以继承一个或多个父类 """ class Parent1: pass class Parent2: pass class Sub1(Parent1): # 单继承 pass class Sub2(Parent1, Parent2): # 多继承 pass print(Sub1.__bases__) # (<class '__main__.Parent1'>,) print(Sub2.__bases__) # (<class '__main__.Parent1'>, <class '__main__.Parent2'>) """ Ps:在python2中有金典类和新式类之分: 新式类:继承了object类的子类,以及该类的子类子子类 经典类:没有继承object类的子类,以及该类的子类子子类 Ps:在python3中没有继承任何类,那么会默认继承object类,所以python3中所有的类都叫新式类。 所以为了兼容Python2,我们可以在创建类的时候写上继承object(如果没有要求要继承其他类) 例如:class Person(object) """ # 二、python的多继承 # 优点:子类可以同事遗传多个父类的属性,最大限度的重用代码 # 缺点: # 1、违背人的思维习惯:继承表达的是一种什么是'什么'的关系 # 2、代码可读性变差 # 3、不建议使用多继承,可扩展性太差 # ps:如果真的涉及到一个子类不可避免的要重用多个父类的的属性,应该使用Mixins机制 # 三、如何使用继承: 为了解决类与类之间的冗余问题 # 示范: class ChwPeople(object): school_name = 'chw' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex class Student(ChwPeople): # school_name = 'chw' # def __init__(self, name, age, sex): # self.name = name # self.age = age # self.sex = sex def choose_course(self): print(f'{self.name}正在选课') stu1 = Student('s1', 16, '男') # 继承之后当前类找不到就会去父类找 print(stu1.__dict__) # {'name': 's1', 'age': 16, 'sex': '男'} print(stu1.school_name) # chw # 尖叫提示:如果父类中有定义了属性和方法,子类中也定义,就叫派生 例如Teacher类的school_name和__init__ class Teacher(ChwPeople): school_name = 'chw' # 派生 # 派生 def __init__(self, name, age, sex, salary, level): # self.name = name # 因为该类的基类中定义了这三个属性,所以不需要自己定义 # self.age = age # 因为该类的基类中定义了这三个属性,所以不需要自己定义 # self.sex = sex # 因为该类的基类中定义了这三个属性,所以不需要自己定义 # 所以要指名道姓的跟基类要: ChwPeople.__init__(self, name, age, sex) self.salary = salary self.level = level def sorce(self): print(f'{self.name}老师在给学生打分') t1 = Teacher('李老师', 48, '男', 15000, 'A') # print(t1.__dict__) # {'salary': 15000, 'level': 'A'} 【没有加ChwPeople.__init__(self, name, age, sex)这行代码】注释掉后只拿到了两个属性,说明调用的是类Teacher中的init方法 print(t1.__dict__) # 【加了ChwPeople.__init__(self, name, age, sex)这行代码】 {'name': '李老师', 'age': 48, 'sex': '男', 'salary': 15000, 'level': 'A'} """ 继承中的菱形继承(死亡钻石) 1、什么是菱形继承: 类:D多继承B和C , B和C都继承A ,A又是一个非object的类。 这种就叫做菱形继承 2、菱形结构带来的问题: 属性查找顺序不一致:【深度优先查找】(一天路走到黑)和【广度优先查找】(最后在找根结点) 【深度优先查找】(金典类用的):沿着一个分支一直找到根结点,在找下一个分支(后面就不会找根结点了,因为已经找过了),直至找到。 【广度优先查找】(新式类用的):沿着一个分支一直找,直到不是根结点,在找下一个分支,直至找到,最后在找根节点。 3、属性查找顺序可以用mro来看: 类名.mro() ps:【python3才有,所以mro是广度查找,因为python都是新式类,都会继承object】 类的mro(): 类以及类的对象访问属性都是参照该类的mro列表,也就是类中属性查找顺序,但是object一定是最后一个找的 总结: 如果多继承是【非菱形继承】,python2和python3中类的属性查找顺序一样,都是一个一个分支找下去,最后在找object 如果多继承是【菱形继承】,python2(中的经典类)和python3(新式类)中类的属性查找顺序不一样,前者是深度优先查找,后者是广度优先查找 """ class A: 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, C): pass class E(C, B): pass """ 类的mro(): 类以及类的对象访问属性都是参照该类的mro列表,也就是类中属性查找顺序,但是object一定是最后一个找的 """ obj = D() # 类D以及类D的对象访问属性都是参照该类的mro列表 print( D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, # <class 'object'>] obj.test() # from B obj = E() print( E.mro()) # [<class '__main__.E'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>] obj.test() # from C """ 继承总结: 一、多继承到底又不要用? 要,但是要规避几点问题: 1、继承结构尽量不要过于复杂 2、推荐使用mixins机制:要在多继承的背景下满足继承的什么"是"什么的关系 ==> mixins """ """ 多继承的正确打开方式: mixins机制 核心:就是在多继承背景下尽可能的提升多继承的可读性 """ # 交通工具类 class Vehicle(object): def fly(self): pass # 民航飞机类 class MinHangFeiJi(Vehicle): pass # 直升飞机类 class ZhiShengFeiJi(Vehicle): pass # 汽车类 class Car(Vehicle): # 汽车不会非飞,但是按照上述继承关系,他也会飞,所以得新建一个飞行工具的类 pass print("======这是一条华丽的分割线=======") # 交通工具类 class Vehicle(object): pass # 飞行工具 class FlyableMixin(): # 用Mixin后缀来标识他只是用来记录是属于部分分类的交通工具额外的功能,java中只有单继承,用接口来解决此问题 def fly(self): pass # 爬行工具 class PaxingMixin(): # 用Mixin后缀来标识他只是用来记录是属于部分分类的交通工具额外的功能,java中只有单继承,用接口来解决此问题 def pa(self): pass # 民航飞机类 class MinHangFeiJi(Vehicle, PaxingMixin): pass # 直升飞机类 class ZhiShengFeiJi(Vehicle, PaxingMixin): pass # 汽车类 class Car(Vehicle): pass """ 在子类派生的新方法中重用父类的功能: 方式一:指名道姓调用某一个类下的函数 ==> 不依赖于继承关系 方式二:super(),调用父类提供给自己的方法 ==> 严格的依赖继承关系 调用super()会得到一个特殊的对象,该对象会参照当前类的mro,去当前类的父类中找属性 尖叫提示⚠️:super是根据发起属性查找的那个类的mro。去当前类中找属性 """ # 方式一、指名道姓调用某一个类下的函数 class C1: def __init__(self, name): self.name = name def f1(self): print('C1 f1') class B1(C1): def __init__(self, name, b1, b2): C1.__init__(self, name) # 方式一:指名道姓调用某一个类下的函数 self.b1 = b1 self.b2 = b2 b1 = B1('b1', 1, 1) print(b1.__dict__) # {'name': 'b1', 'b1': 1, 'b2': 1} # 方式二、super(),调用父类提供给自己的方法 class C1: def __init__(self, name): self.name = name def f1(self): print('C1 f1') class B1(C1): def __init__(self, name, b1, b2): # C1.__init__(self, name) # 方式一:指名道姓调用某一个类下的函数 # super().__init__(name) # python2写法:调用的是方法,自动传入对象 super(B1, self).__init__(name) # python3写法:调用的是方法 self.b1 = b1 self.b2 = b2 b1 = B1('b1', 1, 1) print(b1.__dict__) # {'name': 'b1', 'b1': 1, 'b2': 1} # 特别提醒⚠️: # 尖叫提示⚠️:super是根据发起属性查找的那个类的mro。去当前类中找属性 class A: def test(self): print('A test') class B: def test(self): print('B test') class C(A,B): pass c = C() c.test() # A test # 广度查找 class A: def test(self): print('A test') super(A, self).test1() class B: def test(self): print('B test') # def test1(self): # print('B test1') class C(A,B): def test1(self): print("C test1") c = C() print(C.mro()) # [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>] # c.test() # AttributeError: 'super' object has no attribute 'test1'
这篇关于Python基础53:面向对象三大特性--继承的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-04Python外包有哪些常见的主要库-icode9专业技术文章分享
- 2024-10-02基于深度学习的钢铁缺陷检测系统(yolov8、注意力机制、PyQt5界面、Python)
- 2024-10-01怎么用python搭建一个系统-icode9专业技术文章分享
- 2024-09-30Python基础入门教程
- 2024-09-30获取参数学习:Python中的基础教程
- 2024-09-30Python编程基础详解
- 2024-09-29点击加载学习:Python编程基础教程
- 2024-09-29数据科学五大Python前端库:第二部分
- 2024-09-27使用python 将ETH账户的资产打散
- 2024-09-26Python编程基础