Python基础53:面向对象三大特性--继承

Python基础53:面向对象三大特性--继承,第1张

概述#**************************************************************************#Python学习#**************************************************************************#**所属主题:类#**所属分层:05面向对象三大特性--继承#**功能描述:05面向对象三
# **************************************************************************# Python学习# **************************************************************************# ** 所属主题: 类# ** 所属分层: 05 面向对象三大特性--继承# ** 功能描述: 05 面向对象三大特性--继承# ** 创 建 者: 陈红伟# ** 创建日期: 2021/6/19 5:53 下午# **************************************************************************# ** 修改日期     修改人    修改内容# ** 2021/6/19   陈红伟    新增学习内容代码# **************************************************************************"""本章内容:    继承:        单继承,多继承,__bases__(查看类继承关系) , __dict__(查看对象中的属性),        经典类,新式类,派生(重写),菱形继承,深度优先查找,广度优先查找,mro(),Mixins机制""""""一、什么是继承1、继承是一种创建新类的方式,新建的子类可称之为子类或者派生类,父类又可以称之为基类或超类,子类会遗传父类的属性2、需要注意的是python支持多继承    在python中,新建的类可以继承一个或多个父类"""class Parent1:    passclass Parent2:    passclass Sub1(Parent1):  # 单继承    passclass Sub2(Parent1, Parent2):  # 多继承    passprint(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 = sexclass 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):    passclass 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 Bobj = 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):  # 汽车不会非飞,但是按照上述继承关系,他也会飞,所以得新建一个飞行工具的类    passprint("======这是一条华丽的分割线=======")# 交通工具类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 = b2b1 = 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 = b2b1 = 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):    passc = 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:面向对象三大特性--继承全部内容,希望文章能够帮你解决Python基础53:面向对象三大特性--继承所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1184609.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存