菜鸟学Python第二十二天

面向对象的三大特性之继承

  1. 什么是继承

    1. 继承是一种创建新类的方式,新建的类可以继承一个或者多个父类(python支持多继承),父类又可以称为基类又或超类,新建的类称为派生类或者子类.

    2. 子类会'遗传'父类的属性(特征和技能),从而解决代码重用的问题

class Father:  # 父类
    height = tall
    
class Son(Father):  # 子类,需要将父类传入
    passprint(Son.height)  #子类直接调用的父类中的属性
  1. 继承与抽象

    • 继承描述的是子类与父类之间的关系,是子类可以用父类中所有属性的方式,所以要对父类进行抽取,不能出现子类不应该有的属性,即抽象

    • 抽象是一种概念性的描述方式,表达的是抽取子类中共同的相似点,新建出一个公共父类.抽象的主要的作用是划分类别(达到隔离关注点,降低复杂度的目的)

    • 所以在编程中与要先分析公共属性抽象后,再继承建立子类

  2. 派生

    • 派生类 : 子类中除有父类中公用的属性外,还应该有自己独特的属性,这种含有自己独特属性的子类被称之为派生类

    • 注意:一旦重新定义了自己的属性且与父类重名,那么调用重定义属性时,就以自己为准.

      即子类中出现了与父类重复的名字,称之为覆盖, 子类出现了与父类不同的名字 称之为派生

     

  3. 子类中调用父类中的方法

    方法一: 指名道姓,即父类名.父类方法()

    方法二:super() 表示创建一个特殊的对象 用于调用父类的方法

    !--了解:在python2中super的使用方式有所不同,需要传入当前类和当前对象--

    # 方法一:指名道姓
    class Human:
    ​
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
            print(self)
    ​
        def sayhello(self):
            print('hello 我是%s 今年%s岁 性别:%s' % (self.name, self.age, self.sex))
    ​
    ​
    class Student(Human):
        def __init__(self, name, age, sex, number):
            Human.__init__(self, name, age, sex)
            self.number = number
    ​
        def sayhello(self):
            print('heeeello...')
            Human.sayhello(self)
    ​
    ​
    stu1 = Student('JASSON', 18, 'Male', '123')
    stu1.sayhello()
    ​
    # 输出结果
    heeeello...
    hello 我是JASSON 今年18岁 性别:Male
    ​
    ​
    ​
    # 方法二:super()
    ​
    ...
    class Student(Human):
        def __init__(self, name, age, sex, number):
        # 在python中super()等同于super(Human,self),而super(Human,self)就相当于实例本身
            super.__init__(self, name, age, sex)
            self.number = number
    ​
        def sayhello(self):
            print('heeeello...')
            Human.sayhello(self)
    ​
    # 输出结果
    heeeello...
    hello 我是JASSON 今年18岁 性别:Male
        
        
        
        
    注意:
        当你使用super()函数时,Python会在MRO列表上继续搜索下一个类。只要每个重定义的方法统一使用super()并只调用它一次,
    那么控制流最终会遍历完整个MRO列表,每个方法也只会被调用一次(注意注意注意:使用super调用的所有属性,都是从MRO列表当前
    的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表) ​
  4. 存在继承关系后的属性/方法查找

    • 优先查找对象,对象中没有就查找类,类中没有就查找父类,知道不存在父类时都没找到则报错.

    • (了解内容)存在多个父类时的属性查找顺序:

      1. 第一种情况:

        按照定义中传入父类的先后顺序查找

        1.          

      1. 第二种情况:

        1. 存在父类不存在共同父类时(树状结构):深度优先,按照传入父类的顺序查到底,如果没有则查找下一条线,直到查到或查不到报错

          1.                             

        2. 存在的父类存在共同父类时(菱形结构):广度优先,先按照传入父类的顺序查,止步于最后的公共父类,直到所有对象的父类查找完毕后最后查找公共父类.

          1.       

        3. 菱形结构与树状结构的组合(混合结构):将菱形结构整体看做树状结构的一种,其内部仍然以菱形结构查找,查找完毕后进行树状结构.

          1.       

  5. 经典类与新式类(了解)

    • 新式类:所有直接继承或者间接继承object的类 都是新式类

      object 称之为根类,意思是所有类都源自与object类

      这么设计的目的:object提供了一些常用的基础操作

    • 注意:

      • python 3中默认所有类都是新式类

      • python 2中默认是经典类(不会自动继承object)

  6. mro (了解)

    • 子类名.mro ():表示属性的查找顺序列表,属性查找就是按照该列表来查找的

"""
super访问父类内容时 按照mro列表属性查找
"""
​
​
class S:
    def f1(self):
        print("s f1")
​
​
class A(S):
    pass
​
​
class B(S):
    def f1(self):
        print("b f1")
​
    pass
​
​
class C(A, B):
    def f2(self):
        print("c f2")
        super().f1()
​
​
print(C.mro())
​
​
# 输出结果 (从左到右即为查找顺序)
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.S'>, <class 'object'>]
​

 

 

猜你喜欢

转载自www.cnblogs.com/liusijun113/p/10121376.html
今日推荐