Skip to content

继承是什么 ​

继承描述的是两个类之间的关系:子类继承父类,就可以获取到父类中的属性和方法。

为什么要用它?看这个例子:燃油车和电车都需要"启动、停止、行驶",如果各写一遍就是重复代码。把公共部分抽出来做成 Car(父类),两种车继承它即可:

python
class Car:
    def __init__(self, brand, model, color):
        self.brand = brand
        self.model = model
        self.color = color

    def start(self):
        print(f'{self.brand} {self.model} 正在启动...')

    def stop(self):
        print(f'{self.brand} {self.model} 停止行驶...')

    def run(self):
        print(f'{self.brand} {self.model} 正在行驶...')


class FuelCar(Car):        # 子类(父类):括号里写父类的类名
    pass


class ElectricCar(Car):
    pass
python
c1 = FuelCar("BMW", "X5", "黑色")   # 子类不需要自己写 __init__,直接用父类的
c1.start()   # BMW X5 正在启动...
c1.run()     # BMW X5 正在行驶...

IMPORTANT

子类会把父类**公共的(非私有)**属性和方法继承下来,私有的继承不到。所以父类里 self.__owner 这类私有属性,子类无法直接使用(可以先调父类的 get_owner() 取脱敏值)。

方法重写 ​

重写是指子类继承父类后,如果父类中的方法不满足需求,可以在子类中重新定义一个同名方法,从而用子类的实现替换父类的实现。

python
class Car:
    def charge(self):
        print(f'{self.brand} {self.model} 正在补充燃料...')


class FuelCar(Car):
    def charge(self):
        Car.charge(self)                       # 方式二:父类名.方法名(self)
        print(f'{self.brand} {self.model} 正在加油...')


class ElectricCar(Car):
    def charge(self):
        super().charge()                       # 方式一:super().方法名()
        print(f'{self.brand} {self.model} 正在充电...')
问题答案
什么是重写?在子类中重新定义与父类同名的方法,用子类自己的实现替换父类的实现
如何在子类里调用父类的方法?方式一 super().方法名();方式二 父类名.方法名(self)

多继承与 MRO ​

多继承指的是一个子类同时继承多个父类(会把多个父类中非私有的属性和方法都继承下来)。

python
class XiaomiAiDriving:                     # 智驾系统
    def __init__(self, version="V1.0"):
        self.version = version

    def run(self):
        print(f'使用智驾系统{self.version}正在行驶...')


class SmartCar(Car, XiaomiAiDriving):      # 同时继承两个父类
    def __init__(self, brand, model, color, version="V1.0"):
        Car.__init__(self, brand, model, color)
        XiaomiAiDriving.__init__(self, version)

    def run(self):
        Car.run(self)                      # 两个父类的 run 都想用,就都显式调用
        XiaomiAiDriving.run(self)

NOTE

MRO:Method Resolution Order(方法解析顺序)。当一个类继承了多个父类时,默认优先使用第一个父类中的同名属性或方法;查看顺序可以用 类名.__mro__ 属性或 类名.mro() 方法。

相关 ​

练习题 ​

一、知识回顾(读完直接做下面的实践题) ​

  1. 继承描述的是两个类之间的关系:子类继承父类,就能获取父类的属性和方法
  2. 继承的语法:class 子类(父类):
  3. 子类能继承父类只有非私有的属性和方法
  4. 重写是指在子类中重新定义与父类同名的方法,用子类的实现替换父类
  5. 在子类里调用父类方法有两种写法:super().方法名() 和 父类名.方法名(self)
  6. 多继承的语法:class 子类(父类1, 父类2):;同名方法默认优先使用第一个父类的
  7. 查看方法解析顺序用 类名.__mro__ 属性或 类名.mro() 方法,缩写是 MRO(Method Resolution Order,方法解析顺序)

二、裸写题 ​

  • - 提示(先自己想,实在想不出再点开)

    一级 · 思路:公共的属性/方法放父类,子类只写 class 子类(父类): pass二级 · 方法:class Dog(Animal):三级 · 骨架:子类不用写 __init__,直接用父类的

    - 参考答案(做完再点开)

    python
    # 2-1
    class Animal:
        def __init__(self, name):
            self.name = name
    
        def speak(self):
            print(f'{self.name} 发出声音...')
    
    
    class Dog(Animal):
        def speak(self):
            super().speak()          # 2-2:先调父类实现
            print(f'{self.name}: 汪汪!')
    
    
    class Cat(Animal):
        def speak(self):
            super().speak()
            print(f'{self.name}: 喵喵~')
    
    
    d = Dog("旺财")
    c = Cat("咪咪")
    d.speak()
    c.speak()
  • - 提示(先自己想,实在想不出再点开)

    一级 · 思路:写一个和父类同名的方法即可覆盖 二级 · 方法:super().speak()三级 · 骨架:先 super().speak() 再打印子类特有的声音

    - 参考答案(做完再点开)

    python
    # 2-2:重写 speak —— 先 super() 调父类实现,再写自己的实现
    class Dog(Animal):
        def speak(self):
            super().speak()
            print(f'{self.name}: 汪汪!')
    
    
    class Cat(Animal):
        def speak(self):
            super().speak()
            print(f'{self.name}: 喵喵~')
    
    
    d = Dog("旺财")
    c = Cat("咪咪")
    d.speak()
    c.speak()
  • - 提示(先自己想,实在想不出再点开)

    一级 · 思路:多继承把两个父类的本事合到一个子类;用 MRO 确认同名方法用谁的 二级 · 方法:class GuideDog(Dog, Trained): / GuideDog.__mro__三级 · 骨架:for c in GuideDog.__mro__: print(c.__name__)

    - 参考答案(做完再点开)

    python
    # 2-3:多继承(Dog、Animal 见 2-1)
    class Trained:
        def guide(self):
            print("正在引导主人过马路...")
    
    
    class GuideDog(Dog, Trained):     # 2-3:多继承
        pass
    
    
    g = GuideDog("豆豆")
    g.speak()        # 用 Dog 的 speak
    g.guide()        # 用 Trained 的 guide
    
    for cls in GuideDog.__mro__:
        print(cls.__name__)   # GuideDog → Dog → Animal → Trained → object