继承与派生、组合、菱形继承、多态

                一、继承与派生

    1.什么是继承

        继承是一种新建类的方式,新建的类称为子类,被继承的类称为父类

        继承的特性是:子类会遗传父亲的属性

        强调:继承是类与类之间的关系

    2.为什么用继承

        继承的好处就是可以减少代码的冗余

    3.如何用继承

        在python中支持一个类同时继承多个父类

        在python3中:

            如果一个类没有继承任何类,那默认继承object类

        在python2中:

            如果一个类没有继承任何类,不会继承object类

 

        新式类:

            单凡继承了object的类以及该类的子类,都是新式类

        经典类:

            没有继承object的类以及该类的子类,都是经典类

 

        在python3中都是新式类,只有在python2中才区别新式类与经典类

 

 

            class Parent1(object):

                pass

 

            class Parent2(object):

                pass

 

            class Sub1(Parent1,Parent2):

                pass

 

            # print(Sub1.__bases__)

            print(Parent1.__bases__)

            print(Parent2.__bases__)

 

二、继承的应用

        #派生:子类中新定义的属性,子类在使用时始终以自己的为准

        class OldboyPeople:

            school = 'oldboy'

            def __init__(self,name,age,sex):

                self.name = name #tea1.name='egon'

                self.age = age #tea1.age=18

                self.sex = sex #tea1.sex='male'

 

 

        class OldboyStudent(OldboyPeople):

            def choose_course(self):

                print('%s is choosing course' %self.name)

 

 

        class OldboyTeacher(OldboyPeople):

            #            tea1,'egon',18,'male',10

            def __init__(self,name,age,sex,level):

                # self.name=name

                # self.age=age

                # self.sex=sex

                OldboyPeople.__init__(self,name,age,sex) #指名道姓访问某一个类的函数

                self.level=level

 

            def score(self,stu_obj,num):

                print('%s is scoring' %self.name)

                stu_obj.score=num

 

        stu1=OldboyStudent('耗哥',18,'male')

        tea1=OldboyTeacher('egon',18,'male',10)

 

        #对象查找属性的顺序:对象自己-》对象的类-》父类-》父类。。。

        # print(stu1.school)

        # print(tea1.school)

        # print(stu1.__dict__)

        # print(tea1.__dict__)

 

        tea1.score(stu1,99)

 

        print(stu1.__dict__)

 

 

        # 在子类派生出的新功能中重用父类功能的方式有两种:

        #1、指名道姓访问某一个类的函数:该方式与继承无关

 

 

 

        小练习:

             class Foo:

                def f1(self):

                    print('Foo.f1')

 

                def f2(self):

                    print('Foo.f2')

                    self.f1()

 

            class Bar(Foo):

                def f1(self):

                    print('Bar.f1')

 

            #对象查找属性的顺序:对象自己-》对象的类-》父类-》父类。。。

            obj=Bar()

            obj.f2()

            '''

            Foo.f2

            Bar.f1

            '''

 

 

三、组合

1.什么是组合

    组合就是一个类的对象具备某一个属性,该属性的值是指向另外一个类的对象

 

2.为何用组合

    组合也是用来解决类与类之间代码冗余问题的

 

3.如何用组合

        class Course:

            def __init__(self, name, period, price):

                self.name = name

                self.period = period

                self.price = price

 

            def tell_info(self):

                msg = '''

                课程名:%s

                课程周期:%s

                课程价钱:%s

                ''' % (self.name, self.period, self.price)

                print(msg)

 

 

        class OldboyPeople:

            school = 'oldboy'

 

            def __init__(self, name, age, sex):

                self.name = name

                self.age = age

                self.sex = sex

 

 

        class OldboyStudent(OldboyPeople):

            def __init__(self, name, age, sex,stu_id):

                OldboyPeople.__init__(self, name, age, sex)

                self.stu_id = stu_id

 

            def choose_course(self):

                print('%s is choosing course' % self.name)

 

 

        class OldboyTeacher(OldboyPeople):

            def __init__(self, name, age, sex, level):

                OldboyPeople.__init__(self, name, age, sex)

                self.level = level

 

            def score(self, stu, num):

                stu.score = num

                print('老师[%s]为学生[%s]打分[%s]' % (self.name, stu.name, num))

 

        #创造课程

        python=Course('python全栈开发','5mons',3000)

        linux=Course('linux运维','5mons',800)

 

        #创造学生与老师

 

        stu1=OldboyStudent('猪哥',19,'male',1)

        tea1=OldboyTeacher('egon',18,'male',10)

 

 

        #将学生、老师与课程对象关联/组合

        stu1.course=python

        tea1.course=linux

 

        stu1.course.tell_info()

        tea1.course.tell_info()

 

        #定义一个学生类为了得到学生对象 , 定义一个课程类为了得到课程对象,刚开始两者没关系

        我让学生对象具备某一个属性,而这个属性的值来自另外一个类。stu1.course定位到课程类对象。

        stu1的课程属性是属于学生对象属性,这个属性来自另外一个类,就可以用stu1.course.可以用到左侧

        对象,类的所有东西

 

 

 

四、菱形继承问题

        1.菱形继承:

            当一个子继承多个父类时,多个父类最终继承了同一个类,称之为菱形继承

 

        2.菱形继承的问题:

            python2区分经典类与新式类,如果子的继承是一个菱形,那么经典类与形式的区别为?

                经典类下查找属性:深度优先查找

                新式类下查找属性:广度优先查找

 

 

            class G(object):

                # def test(self):

                #     print('from G')

                pass

 

            class E(G):

                # def test(self):

                #     print('from E')

                pass

 

            class B(E):

                # def test(self):

                #     print('from B')

                pass

 

            class F(G):

                # def test(self):

                #     print('from F')

                pass

 

            class C(F):

                # def test(self):

                #     print('from C')

                pass

 

            class D(G):

                # def test(self):

                #     print('from D')

                pass

 

            class A(B,C,D):

                def test(self):

                    print('from A')

                # pass

 

            obj=A()

            print(A.mro())

            # obj.test() #A->B->E-C-F-D->G-object

 

            继承原理(C3算法与mro)继承原理 MRO列表就是一个简单的所有基类的线性顺序列表

 

 

 

 

 

 

 

 

五、在子派生的新方法中重用父类功能的两种方式

 

    方式一:

            指名道姓法,直接用:类名.函数名

        class OldboyPeople:

            school = 'oldboy'

 

            def __init__(self, name, age, sex):

                self.name = name

                self.age = age

                self.sex = sex

 

        class OldboyStudent(OldboyPeople):

            def __init__(self, name, age, sex, stu_id):

                OldboyPeople.__init__(self, name, age, sex)

                self.stu_id = stu_id

 

            def choose_course(self):

                print('%s is choosing course' % self.name)

 

    方式二:

            严格依赖继承属性查找关系

        super()会得到一个特殊对象,该对象就是专门用来访问父类中的属性(按照继承关系)

        super().__init__(不用为self传值)

 

        注意:

        super的完整用法是super(自己的类名,self),在python2中需要写完整,而python3中可以写super()

        

        强调:二者使用哪一种都可以,但最好不要混合使用

               

        lass OldboyPeople:

            school = 'oldboy'

        

            def __init__(self, name, age, sex):

                self.name = name

                self.age = age

                self.sex = sex

        

        

        class OldboyStudent(OldboyPeople):

            def __init__(self, name, age, sex, stu_id):

                super().__init__(name,age,sex)           ######

                # OldboyPeople.__init__(self, name, age, sex)

                self.stu_id = stu_id

        

            def choose_course(self):

                print('%s is choosing course' % self.name)

        

        stu1=OldboyStudent('egon',19,'male',10)

        print(stu1.__dict__)

 

 

    小练习:

                class A:

                    def f1(self):

                        print('A.f1')

                

                

                class B:

                    def f2(self):

                        super().f1()

                        print('B.f2')

                

                

                class C(B, A):

                    pass

                

                obj=C()

                obj.f2()

                

                

                print(C.mro())  # C->B->A->object   B没有继承A,但super会基于C.mro()继续往后找  

                                                     super严格依赖继承关系,从当前类的下一个类开始查找

                # A.f1

                  B.f2

 

 

 

六、多态与多态性

        1.什么是多态

            多态指的是同一种事物的多种状态

            水--》冰、水蒸气、液态水

            动物——》人、狗、猪

        2.为什么用多态

            多态性:继承同一个类的多个子类有相同的方法名

            那么子类产生的对象就可以不用考虑具体类型而直接调用功能

            

        3.如何用

            动物多态:

            import abc    #abc=abstract class

            

            class Animal(metaclass=abc.ABCMeta):

                @abc.abstractmethod

                def speak(self):

                    pass

                @abc.abstractmethod

                def eat(self):

                    pass

            

            # Animal() #强调:父类是用来指定标准的,不能被实例化

            

            class People(Animal):

                def speak(self):

                    print('say hello')

            

                def eat(self):

                    pass

            

            class Dog(Animal):

                def speak(self):

                    print('汪汪汪')

            

                def eat(self):

                    pass

            class Pig(Animal):

                def speak(self):

                    print('哼哼哼')

            

                def eat(self):

                    pass

  

 python推崇的是鸭子类型,只要你叫的声音像鸭子,并且你走路的样子也像鸭子,那你就是鸭子  

  

            

      

      多态性是指在不考虑实例类型情况下使用实例     

            class Disk:

                def read(self):

                    print('disk read')

            

                def write(self):

                    print('disk wirte')

            

            

            class Process:

                def read(self):

                    print('process read')

            

                def write(self):

                    print('process wirte')

            

            

            class File:

                def read(self):

                    print('file read')

            

                def write(self):

                    print('file wirte')

 

 

 

posted @ 2018-06-27 18:31  Shinonon  阅读(207)  评论(0编辑  收藏  举报