美文网首页
Python的继承

Python的继承

作者: 上发条的树 | 来源:发表于2016-05-18 14:27 被阅读221次

    何为继承

    • 在现实生活中,继承,意味着一个人从另外一个人那里得到了某些东西,比如优秀的品质或者万贯的家财。
    • 在编程中,继承相对来说是有明确规定和预期结果的。类别A继承制类别B,那么A称之为子类,B称之为父类或者超类。
      继承使得子类拥有父类的非私有方法和属性,子类中可以不用写重复的代码。而子类继承父类的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类原有的属性很方法,使其获得与父类不同的功能。子类可以有属于自己的属性和方法。

    继承的意图和好处

    • 可以实现代码重用,但不仅仅只是重用,有时根本就没有重用。
    • 实现属性、方法的继承

    从技术上说,OOP 里,继承最主要的用途是实现多态。对于多态而言,重要的是接口继承性,属性和行为是否存在继承性,这是不一定的。事实上,大量工程实践表明,重度的行为继承会导致系统过度复杂和臃肿,反而会降低灵活性。因此现在比较提倡的是基于接口的轻度继承理念。这种模型里因为父类(接口类)完全没有代码,因此根本谈不上什么代码复用了。

    在 Python 里,因为存在 Duck Type,接口定义的重要性大大的降低,继承的作用也进一步的被削弱了。

    另外,从逻辑上说,继承的目的也不是为了复用代码,而是为了理顺关系。

    例子:

    代码:

    >>> class Person:
    ...     def setName(self,n):
    ...         print "my name is:",n
    ...     def sayHello(self):
    ...         print "hello word"
    ...     def setAge(self,n):
    ...         print "my age is:",n
    ... 
    >>> class Boy(Person):
    ...     def setName(self):
    ...         print "the name is : wxx"
    ...     def setHeight(self):
    ...         print "the height is 175"
    ...
    
    >>> boy = Boy()
    >>> boy.setName()
    the name is : wxx
    
    >>> boy.sayHello()
    hello word
    
    >>> boy.setAge(23)
    my age is: 23
    
    >>> boy.setHeight()
    the height is 175
    
    

    说明:

    • 定义一个Person类,类中定义了三个方法,而且没有初始化函数,初始化函数在类中并不是不可或缺的。
    • 又定义了一个Boy类,继承自Person类。因此,Boy是Person的子类,Person是Boy的父类。
    • 在Boy中,拥有了父类Person的三个方法,因此实例化之后可以调用父类的方法。setName(self) 则是方法的重写。setName()则是子类自己的方法。

    多重继承

    即父类不止一个。

    >>> class AA(object):
    ...     def ADef(self):
    ...         print "AA ADef"
    ... 
    >>> class BB(object):
    ...     def BDef(self):
    ...         print "BB BDef"
    ... 
    >>> class CC(AA,BB):
    ...     pass
    ... 
    >>> cc = CC()  #实例化CC类
    >>> cc.ADef()
    AA ADef
    >>> cc.BDef()
    BB BDef
    >>> 
    
    

    多重继承的顺序

    如果一个子类继承自两个父类,而两个父类中拥有相同的方法或属性,子类会调用谁的?
    举个例子:

    >>> class K1(object):
    ...     def foo(self):
    ...         print "K1-foo"
    ... 
    >>> class K2(object):
    ...     def foo(self):
    ...         print "K2-foo"
    ...     def mod(self):
    ...         print "K2-mod"
    ... 
    
    >>> class J1(K1,K2):
    ...     pass
    ... 
    >>> class J2(K1,K2):
    ...     def mod(self):
    ...         print "J2-mod"
    ... 
    >>> class C(J1,J2):
    ...     pass
    ... 
    
    >>> c = C()
    >>> c.foo()
    K1-foo
    >>> c.mod()
    J2-mod
    

    从以上例子可以看出,实例化C()后,调用foo(),查找foo()的书顺序是:C -> J1 -> J2 ->K1;
    而调用mod(),查找mod()的顺序是:C -> J1 -> J2。
    以上这种继承的属性和方法的查找方式称之为“广度优先”。

    super

    例子

    #!/usr/bin/env python
    # coding=utf-8
    
    __metaclass__ = type
    
    class Person:
        def __init__(self):
            self.height = 160
    
        def about(self, name):
            print "{} is about {}".format(name, self.height)
    
    class Girl(Person):
        def __init__(self):
            super(Girl, self).__init__()
            self.breast = 90
    
        def about(self, name):
            print "{} is a hot girl, she is about {}, and her breast is {}".format(name, self.height, self.breast)
            super(Girl, self).about(name)
    
    if __name__ == "__main__":
        cang = Girl()
        cang.about("wangguniang")
    

    在子类中,init方法重写了,为了调用父类同方法,使用 super(Girl, self).init()的方式。super 函数的参数,第一个是当前子类的类名字,第二个是 self,然后是点号,点号后面是所要调用的父类的方法。同样在子类重写的 about 方法中,也可以调用父类的 about 方法。

    执行结果:

    $ python 20903.py 
    wangguniang is a hot girl, she is about 160, and her breast is 90
    wangguniang is about 160
    

    最后要提醒注意:super 函数仅仅适用于新式类。当然,你一定是使用的新式类。“喜新厌旧”是程序员的嗜好。

    相关文章

      网友评论

          本文标题:Python的继承

          本文链接:https://www.haomeiwen.com/subject/etvirttx.html