Fork me on GitHub

Python学习记录8-继承2

继承

  • 单继承和多继承
    • 单继承:每个类只能继承一个类
    • 多继承:每个类允许继承多个类

    >>> class A():
            pass

    >>> class B(A):
            pass

    >>> class C(B,A):
            pass


    >>> print(A.__mro__)
    >>> print(B.__mro__)

    输出:
    (<class '__main__.A'>, <class 'object'>)
    (<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)

    # 子类可以直接拥有父类的属性和方法,私有属性和方法除外
    >>> class Fish():
            def __init__(self, name):
                self.name = name
            def swim(self):
                print('{} can swimming......'.format(self.name))

    >>> class Bird():
            def __init__(self, name):
                self.name = name

            def fly(self):
                print('{} can fly......'.format(self.name))

    >>> class Person():
            def __init__(self, name):
                self.name = name

            def work(self):
                print("Working......")

    # 单继承的例子
    >>> class Student(Person):
            def __init__(self, name):
                self.name = name          

    # 多继承
    >>> class SuperMan(Person, Bird, Fish):
            def __init__(self, name):
                self.name = name   



    >>> s = SuperMan('小明')
    >>> s.fly()
    >>> s.swim() 

    输出:
    小明 can fly......
    小明 can swimming......   

  • 单继承和多继承的优缺点

    • 单继承:
      • 传承有序逻辑清晰语法简单隐患少
      • 功能不能无限扩展,只能在当前唯一的继承链中扩展
    • 多继承:
      • 优点:类的功能扩展方便
      • 缺点:继承关系混乱
  • 菱形继承/钻石继承

    • 多个子类继承自同一个父类,这些子类又被同一个类继承,于是继承关系图形成一个菱形图谱
    • MRO
    • 关于多继承的MRO
      • MRO就是多继承中,用于保存继承顺序的一个列表
      • python本身采用C3算法来做多继承的菱形继承进行计算的结果
      • MRO列表的计算原则:
        • 子类永远在父类前面
        • 如果多个父类,则根据继承语法中括号内类的书写顺序存放
        • 如果多个类继承了同一个父类,孙子类中只会选取继承语法括号中第一个父类的父类

    # 菱形问题
    >>> class A():
            pass
    >>> class B(A):
            pass
    >>> class C(A):
            pass
    >>> class D(B,C):
            pass
    
  • 构造函数
    • 在对象进行实例化的时候,系统自动调用的一个函数叫构造函数,通常此函数用来实例化对象进行初始化,顾名构造函数,在python中叫魔术函数、魔法函数。
    • 构造函数一定要有,如果没有,则自动向上查找,按照MRO顺序,直到找到为止

    # 构造函数例子
    >>> class Person():
            # 对Person类进行实例化的时候
            # 姓名要确定
            # 年龄得确定
            # 地址肯定有
            def __init__(self):
                self.name = "NoName"
                self.age = 18
                self.address = 'earth'
                print("I am a Student")

    # 实例化一个人
    >>> p = Person()
    >>> print(p.__dict__)    

    输出:
    I am a Student
    {'name': 'NoName', 'age': 18, 'address': 'earth'}

    ---------------------------------------------------------------------------------------------------

     # 构造函数的调用顺序 -1
    # 如果子类没有写构造函数,则自动向上查找,直到找到为止
    >>> class A():
            def __init__(self):
                print("A")

    >>> class B(A):
            def __init__(self):
                print("B")

    >>> class C(B):
            pass

    # 此时,首先查找C的构造函数
    # 如果没有,则向上按照MRO顺序查找父类的构造函数,直到找到为止
    >>> c = C() # C类没有构造函数 找C的父类B 找到了 然后停止 不再向上找

    ---------------------------------------------------------------------------------------------------
    

    # 构造函数的调用顺序 -2
    >>> class A():
            def __init__(self):
                print("A")

    >>> class B(A):
            def __init__(self, name):
                print("B")
                print(name)

    >>> class C(B):
            pass

    # 此时,首先查找C的构造函数
    # 如果没有,则向上按照MRO顺序查找父类的构造函数,直到找到为止
    # 此时,会出现参数结构不对应错误
    # c = C() # 此处 C类没有构造函数 向上找到C的父类B的构造函数 但B类构造函数需要两个参数
    >>> cc = C('哈哈')
    
    输出:
    B
    哈哈

    ---------------------------------------------------------------------------------------------------

    # 构造函数的调用顺序 -3
    >>> class A():
            def __init__(self):
                print("A")

    >>> class B(A):
            def __init__(self, name):
                print("B")
                print(name)

    >>> class C(B):
            # c中想扩展B的构造函数,
            # 即调用B的构造函数后再添加一些功能
            # 有两种方法实现


            ''' 

            # 第一种是通过父类名调用
            def __init__(self, name):
                # 首先调用父类的构造函数
                B.__init__(self, name)
                #其次,再增加自己的功能
                print("这是C中附加的功能")

            '''

            # 第二种,使用super调用
            def __init__(self, name):
                # 首先调用父类构造函数
                super(C, self).__init__(name)
                # 其次,再增加自己的功能
                print("这是C中附加的功能")


    >>> c = C("我是C") 

    输出:
    B
    我是C
    这是C中附加的功能

多态

  • 多态就是同一个对象在不同情况下有不同的状态出现

  • 多态不是语法,是一种设计思想

  • 多态性:一种调用方式,不同的执行效果

  • 多态:同一事物的多种形态,动物分为人类、狗类、猪类

  • 多态和多态性

  • Mixin设计模式

    • 主要采用多继承方法对类的功能进行扩展
  • 我们使用多继承语法来是吸纳Mixin

  • 使用Mixin实现多继承的时候要非常小心

    • 首先他必须表示某一单一功能,而不是某个物品
    • 职责必须单一,如果有多个功能,则写多个Mixin
    • Mixin不能依赖于子类的实现
    • 子类即使没有继承这个Mixin类,也能照样工作,只是缺少了某个功能
  • 优点

    • 使用Minxin可以在不对类进行任何修改的情况下,扩充功能
    • 可以方便的组织和维护不同功能组件的划分
    • 可以根据需要任意调整功能类的组合
    • 可以避免创建很多新的类,导致类的继承混乱

    # Mixin案例
    >>> class Person():
            name = '小明'
            age =18

            def eat(self):
                print("EAT....")

            def drink(self):
                print("Drink....")

            def sleep(self):
                print("SLEEP....")     

    >>> class Teacher(Person):
            def work(self):
                print("WORK....")   

    >>> class Teacher(Person):     
            def work(self):
                print("WORK....")    

    >>> class Student(Person):
            def study(self):
                print("STUDY....")  

    >>> class Tutor(Teacher, Student):
            pass

    >>> t = Tutor()

    >>> print(Tutor.__mro__)
    >>> print(t.__dict__)
    >>> print(Tutor.__dict__)

    >>> print("*" * 20)
    >>> class TeacherMixin():
            def work(self):
                print("Work")

    >>> class StudentMixin():
            def study(self):
                print("Study")


    >>> class TutorM(Person, TeacherMixin, StudentMixin):
            pass

    >>> tt = TutorM()
    >>> print(TutorM.__mro__)
    >>> print(tt.__dict__)
    >>> print(TutorM.__dict__)

    输出:
    (<class '__main__.Tutor'>, <class '__main__.Teacher'>, <class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>)
    {}
    {'__module__': '__main__', '__doc__': None}
    ********************
    (<class '__main__.TutorM'>, <class '__main__.Person'>, <class '__main__.TeacherMixin'>, <class '__main__.StudentMixin'>, <class 'object'>)
    {}
    {'__module__': '__main__', '__doc__': None}

posted @ 2019-10-22 19:34  黄焖鸡米饭-  阅读(145)  评论(0编辑  收藏  举报