8.python之面相对象part.3(

发布时间:2019-09-12 07:54:16编辑:auto阅读(1476)

    在python这门编程语言中,一个类可以去继承一个父类甚至多个父类,只继承一个父类就是单继承,如果一个子类继承了多个父类,那么这就是多继承。原始类被称为“基类”(超类),继承了其他类的新式类被称为“子类”或“派生类”。

    一.如何实现类的继承。

    接下来简单演示下什么是单继承和多继承。

    class dad_1:

        pass

    class dad_2:

        pass

    #新建了两个父类dad_1和dad_2

    class son_1(dad_1):  #单继承:只继承了一个父类

        pass

    class son_2(dad_1,dad_2):  #多继承,同时继承了多个父类

        pass

    print son_1.__bases__

    >>>(<class __main__.dad_1 at 0x108b30870>,)

    print son_2.__bases__

    >>>(<class __main__.dad_1 at 0x107a6e870>, <class __main__.dad_2 at 0x107b661f0>)

    注意!在这里要补充一点,就是,在python中定义了一个类,如果这个类没有指定任何的父类,那么这个类默认会继承一个object类,这个object类是所有父类的“基类”。


    二.一个子类会继承父类的哪些属性?

    子类默认会继承父类所有的方法和属性,当然子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。

    也就是说,当一个子类继承了一个父类的时候,子类或者是子类生成的对象,要找一个属性或者是一个方法,首先会在对象自己身上找,如果找不到,就回到这个对象所属的类中找,如果类中找不到,就会到这个类的父类中找,如果父类中也找不到,回到上一级父类中去找,如果找到基类还没有找到想要找的属性,或者方法,就报错了。


    三.什么时候需要用继承?什么时候需要用组合?

    首先先来说说什么时候比较适合用组合。(由多个小类组合成一个大的类。)

    当每个小类之间差别很大,并且小类是大类所需要的组件的时候,使用组合是不错的选择。

    (关于组合这个概念,博主还没想到很好的例子去演示,想到了后面的文章会补。。。)


    那什么时候适合用继承呢?

    当类之前就很多相似的功能,可以提取这些类所有相似的功能,去做成一个“基类”(父类),在这种情况下使用继承的特性比较好。


    下面是个关于继承的例子:

    class animal:   #首先定义了一个动物类。

        def eat(self):

            print "%s 吃" %(self.name)

        def drink(self):

            print "%s 喝" %(self.name)

        def shit(self):

            print "%s 拉屎" %(self.name)

        def pee(self):

            print "%s 撒尿" %(self.name)

    class cat(animal):   #定义了一个cat类,这个cat类继承了animal动物类。

        def __init__(self,name):

            self.name = name

            self.type = 'cat'

        def say(self):

            print "miao~"

    class dog(animal):  #定义了一个dog类,这个dog类也继承了animal动物类。

        def __init__(self,name):

            self.name = name

            self.type = "dog"

        def say(self):

            print "wang~"

    cat1 = cat("小白")

    dog1 = dog("crea")

    cat1.eat()

    cat.say()

    通过上面的例子可以看到,cat类和dog类并没有定义eat,drink,pee,shit功能,这些功能都是名为从animal的父类中继承而来的。

    所以说,在开发一个程序的时候,如果我们先定义了一个类a,然后又想建立一个类b,其中类b的大部分内容与类a相同的时候,我们不在需要从头写一个类b,大部分的属性和功能从类a中继承就好了。

    通过继承的方式新建类B,让B继承A,B会‘遗传’A的所有属性(数据属性和函数属性),实现代码重用。


    四.python多继承的继承顺序。

    在python中,一个子类如果继承了多个父类,寻找属性和方法的方式有两种,分别是深度优先和广度优先。

    当这个类是经典类时,多继承的情况下,会按照深度优先的方式进行查找。

    当这个类是新式类时,多继承的情况下,会按照广度优先的方式进行查找。

    上面这个深度优先的广度优先的图到底是什么意思呢?下面我来解释一下。

    (下面的解释配合上图食用~)

    深度优先(python2.x版本中的经典类的查找方式):A类分别继承了B类和C类,B类和C类又同时继承的D类,那他们查找属性和方法的方式是,A发现自己没有某个属性和方法时,首先会去查找自己的第一个父类,也就是B,当B这个中也没有相应的属性或者方法,接着也会去查找B类的父类,就是D类,D类已经是这些类的“基类”了,已经没有办法再向上找了,这时目光回到A 类,A同时还继承了一个C类,C类是A类的第二个父类,接下来就回去找C类,如果C类也没有这个属性和方法,就会去找C类的父类......以此类推,一级一级找下去。


    广度优先(python2.x版本中的新式类,以及python3中所有类的查找方式):和上一个例子一样,A类分别继承了B类和C类,B类和C类又同时继承的D类,所谓广度优先,就是,当A发现自己没有某个属性和方法的时候,首先会去找自己的第一个父类,也就是B,当B类中也没有相应的属性或者方法时,此时不会像深度优先一样去找B类的父类,而时去找A自己继承的第二个父类!!C类,当C类中也没有该属性或方法的时候,此时才会去找B类的父类!这就是广度优先。


    在这里重新的!重点强调一下经典类和新式类的概念!!!!!

    在python2.x版本中!!当前类,或者父类继承了object类,那么这个类就是新式类。

    class c1:   #经典类                                    class c1(object):  #新式类

        pass                                                            pass

    class c2(c1): #经典类                              class c2(c1):     #新式类

        pass                                                              pass  

    在python3版本中,所有的类都是新式类。(为什么python3中所有的类都是新式类呢,就是因为你定义一个类,如果这个类不继承任何父类,默认就会继承object类)


    (重点)五.类继承的实现原理。

    python内部是如何实现类继承的?

    在python中定义的每一个类,python内部都会计算出一个方法解析的顺序,也就是一个mro列表,这个mro列表就是一个简单的,所有父类的顺序列表。

    关于mro列表,可以看下面这个例子:

    #!/usr/bin/python2.7

    # -*- coding:utf-8 -*-

    #class person:

     #   def __init__(self,career):

     #       self.career = career

     #   def show_carrer(self):

     #       print self.career

     #   def __del__(self):

    #      print "obj_del!!!!!"

    #ayumi = person("diva")

    #ayumi.show_carrer()

    #ayumi.__del__()

    #print ayumi()

    #import time

    #class num:

    #    count = 0

    #    def __init__(self):

    #        num.count += 1

    #    def __del__(self):

    #        num.count -= 1

    #    @classmethod

    #    def show_count(self):

    #        return num.count

    #    @staticmethod

    #    def dis_time():

    #        return time.localtime()

    #a = num()

    #b = num()

    #print b.dis_time()

    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):

        def test(self):

            print('from D')

    class E(C):

        def test(self):

            print('from E')

    class F(D,E):

        # def test(self):

        #     print('from F')

        pass

    f1=F()

    f1.test()

    print F.__mro__

    >>>from D

    (<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)


    为了实现类的继承,python会在类的mro列表上从左到右开始查找父类,直到找到匹配这个属性的类为止。

    mro列表遵循下面三个原则:

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

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

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

    注意!!python中只有新式类才会有mro列表!经典类没这个东西!!


关键字