继承与多态

一、继承

  1. 什么是继承?

    继承就是新建类的一种方式,新建的类叫作子类或者派生类,被继承的类叫作父类或者基类

  2. 为什么要用继承

    是为了解决类与类之间代码的冗余

  3. 新式类和经典类(python 2中所特有的)

    python 2 和python 3中的类有点不同。在python 2中,类被分为新式类和经典类,新式类是继承了object类的子子孙孙都叫新式类,没有继承object类的子子孙孙都叫经典类。而在python 3中,所有的类都默认继承了object类。

  4. 继承的使用

    # 子类可一继承父类当中的方法
    class School:
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
    
    
    class Teacher(School):
        def __init__(self, name, age, gender, salary):
            self.salary = salary
            School.__init__(self, name, age, gender)
    
        def score(self, stu_obj, goals):
            stu_obj.goals = goals
            print('%s给%s打了%s分' % (self.name, stu_obj.name, goals))
    
    
    class Student(School):
        def __init__(self, name, age, gender):
            School.__init__(self, name, age, gender)
    
        def get_course(self, course=None):
            if course == None:
                course = []
            self.courses = course
    
            
    stu1 = Student('lily', 18, 'female')
    teacher1 = Teacher('Mr Right', 28, 'female', 30000)
    teacher1.score(stu1, 100)
    print(stu1.__dict__)  
    # Mr Right给lily打了100分
    # {'name': 'lily', 'age': 18, 'gender': 'female', 'goals': 100}
    print(teacher1.__dict__)  
    # {'salary': 30000, 'name': 'Mr Right', 'age': 28, 'gender': 'female'}
    

二、属性查找

  1. 单继承下的属性查找

    # 案例一
    class Foo:
        def f1(self):
            print('from FOO')
    
    
    class Bar(Foo):
        def f2(self):
            self.f1()
            print('from Bar')
    
    
    obj1 = Bar()
    obj1.f2() 
    # from FOO
    # from Bar
    
    # 案例二
    class Foo:
        def __f1(self):
            print('f1 from Foo')
    
        def f2(self):
            print('from FOO')
            self.__f1()
    
    
    class Bar(Foo):
        def __f1(self):
            print('from Bar')
    
    
    obj1 = Bar()
    obj1.f2()
    # from FOO
    # f1 from Foo
    
  2. 多继承下的属性查找

    原则:新式类按照广度优先的原则,经典类按照深度优先的原则

    # 案例一:经典类
    class V:
        def f3(self):
            print('f1 from V')
    
    
    class H(V):
        def f2(self):
            print('f2 from H')
    
    
    class A(H):
        def f1(self):
            print('f1 from A')
    
    
    class N(V):
        def f2(self):
            print('f2 from N')
    
    
    class B(N):
        def f1(self):
            print('f1 from B')
    
        def f4(self):
            print('f4 from B')
    
    
    class S(A, B):
        pass
    
    
    obj1 = S()
    obj1.f1()  # f1 from A
    obj1.f2()  # f2 from H
    obj1.f3()  # f1 from V
    obj1.f4()  # f4 from B
    
    # 案例二:新式类
    class A(object):
        def test(self):
            print('from A')
    
    
    class B(A):
        def test(self):
            print('from B')
        pass
    
    class C(A):
        def test(self):
            print('from C')
        pass
    
    
    class D(B):
        def test(self):
            print('from D')
        pass
    
    class E(C):
        def test(self):
            print('from E')
        pass
    
    
    class F(D, E):
        def test(self):
            print('from F')
        pass
    f1 = F()
    f1.test()
    # 全部留下                    >>> from F
    # 注释掉F下面的test 	        >>> from D
    # 注释掉F、D下面的test         >>> from B
    # 注释掉F、D、B下面的test      >>> from E
    # 注释掉F、D、B、E下面的test   >>> from C
    # 注释掉F、D、B、E、C下面的test   >>> from A
    
  3. super()和mro列表

    # super()
    class People():
        school = 'SH'
    
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
            
    class Teacher(People):
    
        def __init__(self, name, age, gender, level):
            self.level = level
            super().__init__(name, age, gender) # super的使用
    

    .mro()

    class A:
        def test(self):
            print('from A.test')
            super().test()
    
    
    class B:
        def test(self):
            print('from B')
    
    
    class C(A, B):
        pass
    
    
    print(C.mro()) # [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
    c = C() 
    c.test() 
    # from A.test 
    # from B
    

三、多态与多态性

  1. 抽象类: 抽象类只能被继承,不能被实例化

    class Animal(metaclass=abc.ABCMeta):
    
        @abc.abstractmethod  # 该方法已经是抽象方法了
        def speak(self): pass
    
        @abc.abstractmethod
        def login(self):pass
    
    class People(Animal):
        def speak(self):
            # print('嗷嗷嗷')
            pass
        def login(self):
            pass
    
    
    class Pig(Animal):
        def speak(self):
            print('哼哼哼')
    
    
    class Dog(Animal):
        def speak(self):
            print('汪汪汪')
    
    
    obj = People()
    obj.speak()
    
  2. 多态带来的特性:在不用考虑对象数据类型的情况下,直接调用对应的函数

    def animal(animal):
        return animal.speak()
    
    animal(obj)
    animal(obj1)
    animal(obj2)
    animal(obj3)
    
    # 父类限制子类的行为
    class Animal():
        def speak(self):
            raise Exception("必须实现speak方法")
    
posted @ 2021-12-06 19:31  recordlife  阅读(33)  评论(0编辑  收藏  举报