• day29 继承


    一、property装饰器

    应用场景1

    当我们需要在类中定义一个属性,他本质是一种方法,但是我们要让他用起来像是一种数据

    # 例 人类的BMI会随着身高或者体重的变化而变化,所以我们在每次修改身高体重时BMI都会动态的变化,但是Bmi本身又是一种数据,用起来以数据的方式会更清晰
    class People:
        def __init__(self, name, weight, height):
            self.name = name
            self.weight = weight
            self.height = height
        @property
        def bmi(self):
            return self.weight // (self.height ** 2)
    obj = People('hz',70,1.82)
    print(obj.bmi)
    >>>21.0
    

    应用场景2

    当我们把类中的某个属性隐藏起来后,可以用property给他们关联查看,删除,修改的操作

    class People:
        def __init__(self, name):
            self.__name = name
        def get_name(self):
            return self.__name
        def set_name(self, val):
            if type(val) is not str:
                print('必须传入str类型')
                return
            self.__name = val
        def del_name(self):
            print('不让删除')
        # 通过property的方法给类的name属性关联查看,修改,删除操作(按顺序)
        name=property(get_name,set_name,del_name)
    obj = People('hz')
    print(obj.name)
    obj.name = 'lxt'
    print(obj.name)
    del obj.name
    

    应用场景3(场景2优化)

    class People:
        def __init__(self, name):
            self.__name = name
    
        @property
        def name(self):
            return self.__name
    
        @name.setter
        def name(self, val):
            if type(val) is not str:
                print('必须传入str类型')
                return
            self.__name = val
    
        @name.deleter
        def name(self):
            print('不让删除')
    
    
    obj = People('hz')
    print(obj.name)
    obj.name = 'lxt'
    print(obj.name)
    del obj.name
    

    二、继承介绍

    定义

    继承是一种创建新类的方式,在Python中,新建的类可以继承一个或多个父类,新建的类可称为子类或派生类,父类又可称为基类或超类

    继承
    优点:解决类与类之间代码冗余
    缺点:将类耦合到一起

    python支持多继承
    优点:最大程度的重用父类的属性
    缺点:
    1 违背了人的思维习惯:继承表达的是一种‘是’什么的关系
    2 代码的可读性变差
    3 不建议使用多继承,有可能会引发可恶的菱形问题,扩展性变差
    如果真的涉及到一个子类不避免的重用多个父类的属性,应该用Mixins

    新式类和经典类

    在Python2中有经典类与新式类之分,没有显式地继承object类的类,以及该类的子类,都是经典类,显式地继承object的类,以及该类的子类,都是新式类。而在Python3中,即使没有显式地继承object,也会默认继承该类

    1 语法

    类是为了减少程序的代码重复,而继承就是为了减少类之间的代码重复

    我们要找到类之间的重复关系,就要先抽象出来类的属性,把重复的统一成父类

    # 老师和学生都属于人类,可以把他们之间的共同属性提取出来放在人类里,再去继承人类
    class People:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    class Student(People):
        def __init__(self,name,age,sex,sno):
            People.__init__(self,name,age,sex)#继承使用人类的属性
            self.sno = sno
        def choose_course(self,course_obj):
            self.course = course_obj
    
    class Teacher(People):
        def __init__(self,name,age,sex,sarly,level):
            People.__init__(self,name,age,sex)#继承使用人类的属性
            self.sarly = sarly
            self.level = level
        def set_score(self,student_obj,valu):
            print(f'{self.name}给{student_obj.name}打分:{valu}')
            student_obj.score = valu
    
    
    stu_obj = Student('hz',18,'male',21346)
    tea_obj = Teacher('egon',111,'male',2000,10)
    tea_obj.set_score(stu_obj,18)
    print(stu_obj.score)
    

    2 属性查找

    对象的属性查找顺序是:对象本身,类,父类

    3 继承的实现原理

    3.1 菱形问题

    大多数面向对象语言都不支持多继承,而在Python中,一个子类是可以同时继承多个父类的,这固然可以带来一个子类可以对多个不同父类加以重用的好处,但也有可能引发著名的 Diamond problem菱形问题(或称钻石问题,有时候也被称为“死亡钻石”),菱形其实就是对下面这种继承结构的形象比喻

    这种继承结构下导致的问题称之为菱形问题:如果A中有一个方法,B和/或C都重写了该方法,而D没有重写它,那么D继承的是哪个版本的方法:B的还是C的?如下所示

    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,C):
        pass
    obj = D()
    obj.test() # 结果为:from B
    

    那么为什么是先继承B呢,想知道这个就必须了解python继承实现的原理

    3.2 继承原理

    python到底是如何实现继承的呢? 对于你定义的每一个类,Python都会计算出一个方法解析顺序(MRO)列表,该MRO列表就是一个简单的所有基类的线性顺序列表,如下

    print(D.mro())
    >>>[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
    

    python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。 而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:

    1.子类会先于父类被检查

    2.多个父类会根据它们在列表中的顺序被检查

    3.如果对下一个类存在两个合法的选择,选择第一个父类

    3.3 深度优先和广度优先

    非菱形结构

    当我们的继承是非菱形结构时,不管是新式类还是经典类都是按照分支一个一个找下去最后找object

    菱形结构

    经典类:深度优先,会在检索第一条分支的时候就直接一条道走到黑,即会检索大脑袋(共同的父类)

    新式类:广度优先,会在检索最后一条分支的时候检索大脑袋

  • 相关阅读:
    EL表达式
    Java反射机制详解
    最小生成树-Prim算法和Kruskal算法
    最短路径—Dijkstra算法和Floyd算法
    servlet的转发与重定向
    SQL常用增删改查
    Java map遍历
    深入理解Java的接口和抽象类
    eclipse快捷键
    Vue父子组件数据双向绑定,子组件可修改props
  • 原文地址:https://www.cnblogs.com/hz2lxt/p/12667151.html
Copyright © 2020-2023  润新知