zoukankan      html  css  js  c++  java
  • Python——继承

    Python的继承是多继承机制,一个子类可以同时有多个直接父类;继承可以得到父类定义的方法,子类就可以复用父类的方法。

    一、继承的语法

    子类:实现继承的类。

    父类(基类、超类):被继承的类。

    子类继承父类是在定义子类时,将多个父类放在子类之后的圆括号内,如果定义类时,未指定这个类的直接父类,则默认继承object类,所以object类是所有类的父类(直接父类或者是间接父类)。

    语法格式如下:

    class SubClass (SuperClassl , SuperClass2 , ... ):
        # 类定义部分
    

    使用例子:

    class Animal:
        def dog(self):
            print ('我有一只狗!他叫%s'%self.dog_name)
    
    class Child:
        def son(self):
            print ('我有两个儿子!')
    
    # 定义Myself类,继承Animal类和Child类
    class Myself(Animal,Child):
        def name(self):
            print ('我叫小明!')
    
    M = Myself()    # 创建Myself对象
    M.dog_name = '大黄'   # 通过Myself对象添加dog_name类变量
    M.dog() # 调用Myself对象的dog()方法,打印 我有一只狗!他叫大黄
    M.son() # 调用Myself对象的son()方法,打印 我有两个儿子!
    M.name()    # 调用Myself对象的name()方法,打印 我叫小明!
    

    在上面的例子中,定义了Animal和Child两个父类,和一个继承Animal类和Child类的Myself类;创建Myself对象后,可以访问Myself对象的dog()方法和son()方法,说明Myself对象也具有dog()方法和son()方法,所以继承可以得到父类定义的方法,通过继承子类就可以复用父类的方法。

    二、多继承

    子类会通过继承得到所有父类的方法,那么如果多个父类中有相同的方法名,排在前面的父类同名方法会“遮蔽”排在后面的父类同名方法,例:

    class Animal:
        def name(self):
            print ('我有一只狗,他叫大黄!')
    
    class Child:
        def name(self):
            print ('我有两个儿子!')
    
    class Myself(Animal,Child):
        pass
    
    class Yourself(Child,Animal):
        pass
    
    M = Myself()
    M.name()    # 打印 我有一只狗,他叫大黄!
    Y = Yourself()
    Y.name()    # 打印 我有两个儿子!
    

    上面例子中,Myself类继承了Animal类和Child类,当Myself子类对象调用name()方法时,因为Myself子类中没有定义name()方法,Python会先在Animal父类中搜寻name()方法,一旦搜寻到就会停止继续向下搜寻,所以运行的是Animal类中的name()方法;而Yourself子类中由于Child父类排在前面,所以运行的是Child类的name()方法。

    三、重写

    子类包含与父类同名的方法称为方法重写(方法覆盖),可以说是重写父类方法,也可以说子类覆盖父类方法。

    例:

    class Animal:
        def name(self):
            print ('我有一只狗,他叫大黄!')
    
    
    class Myself(Animal):
        # 重写Animal类的name()方法
        def name(self):
            print ('我没有狗,我只有一只猫,他叫大白!')
    
    
    M = Myself()    # 创建Myself对象
    M.name()    # 执行Myself对象的name()方法,打印 我没有狗,我只有一只猫,他叫大白!
    

    上面的例子中,运行M.name()时执行的不再是Animal类的fly()方法,而是Myself类的name()方法。

    在子类中重写方法之后,如果需要用到父类中被重写的实例方法,可以通过类名调用实例方法来调用父类被重写的方法。

    例:

    class Animal:
        def name(self):
            print ('我有一只狗,他叫大黄!')
    
    class Myself(Animal):
        # 重写Animal类的name()方法
        def name(self):
            print ('我还有一只猫,他叫大白!')
    
        def pet(self):
            Animal.name(self)   # 调用被重写的父类方法name(),使用类名.实例名调用,需要手动传self
            self.name() # 执行name()方法,会调用子类重写的name()方法
          
      
    M = Myself()    # 创建Myself对象
    M.pet()
    '''
    打印
    我有一只狗,他叫大黄!
    我还有一只猫,他叫大白!
    '''
    

      

    四、super函数调用父类构造方法

    如果子类有多个直接的父类,那么排在前面的构造方法会遮蔽排在后面的构造方法。

    例:

    class Animal:
        def __init__(self,pet,name):
            self.pet = pet
            self.name = name
            
        def favourite_animal(self):
            print ('我有一只%s,他叫%s!'%(self.pet,self.name))
    
    class Fruit:
        def __init__(self,kind):
            self.kind = kind
            
        def favourite_fruit(self):
            print ('我喜欢的水果是%s!'%self.kind)
    
    
    class Myself(Animal,Fruit):
        pass
            
    
    M = Myself('狗','大黄')    # 创建Myself对象
    M.favourite_animal()    # 调用Myself对象的favourite_animal()方法,打印 我有一只狗,他叫大黄!
    M.favourite_fruit() # 调用Myself对象的favourite_fruit方法,由于未初始化Fruit对象的kind实例变量,报错 AttributeError: 'Myself' object has no attribute 'kind'
    

    上面例子中,Myself子类继承了Animal父类和Fruit父类,由于Animal父类排在Fruit父类前面,所以Animal父类的构造函数遮蔽了Fruit父类的构造函数,运行M.favourite_animal()没有任何问题,当运行M.favourite_fruit()时,由于未初始化Fruit对象的kind实例变量,所以程序会报错。

    解决以上问题,Myself应该重写父类的构造方法,子类的构造方法可以调用父类的构造方法,有以下两种方式:

    1.使用未绑定方法,即: 父类名.__init__(self,参数1,参数2....)。

    2.使用super()函数调用父类构造方法。

    先查看一下super()函数的帮助信息,

    >>> help(super)
    Help on class super in module builtins:
    
    class super(object)
     |  super() -> same as super(__class__, <first argument>)
     |  super(type) -> unbound super object
     |  super(type, obj) -> bound super object; requires isinstance(obj, type)
     |  super(type, type2) -> bound super object; requires issubclass(type2, type)
     |  Typical use to call a cooperative superclass method:
     |  class C(B):
     |      def meth(self, arg):
     |          super().meth(arg)
     |  This works for class methods too:
     |  class C(B):
     |      @classmethod
     |      def cmeth(cls, arg):
     |          super().cmeth(arg)
    ...
    

    通过帮助信息,可以看到,当调用父类的实例方法时,会自动绑定第一个参数self;当调用类方法时,会自动绑定第一个参数cls。

    接下来修改上面的程序:

    class Animal:
        def __init__(self,pet,name):
            self.pet = pet
            self.name = name
            
        def favourite_animal(self):
            print ('我有一只%s,他叫%s!'%(self.pet,self.name))
    
    class Fruit:
        def __init__(self,kind):
            self.kind = kind
            
        def favourite_fruit(self):
            print ('我喜欢的水果是%s!'%self.kind)
    
    
    class Myself(Animal,Fruit):
        def __init__(self,pet,name,kind):
            Fruit.__init__(self,kind)   # 通过未绑定方法调用父类构造方法
            super().__init__(pet,name)  # 通过super()函数调用父类构造方法
            
            
                   
    
    M = Myself('狗','大黄','苹果')
    M.favourite_animal()    # 打印 我有一只狗,他叫大黄!
    M.favourite_fruit()     # 打印 我喜欢的水果是苹果!

      

  • 相关阅读:
    从scanf的学习接口设计
    特现C语言编程特点的小代码,itoa,数值转换成字符串
    So many good projects for studying C programming lanuage.
    重要算法代码
    选择一本C++教材
    4412 内核模块传参数
    4412 GPIO初始化
    4412 物理地址
    4412 杂项设备
    4412 Linux设备总线
  • 原文地址:https://www.cnblogs.com/mingmingming/p/11199890.html
Copyright © 2011-2022 走看看