面向对象高级-继承与重写
面向对象高级-继承与重写
继承的语法与"只继承非私有"的规则、方法重写的两种调用父类方式,以及多继承与 MRO 解析顺序
继承是什么
继承描述的是两个类之间的关系:子类继承父类,就可以获取到父类中的属性和方法。
为什么要用它?看这个例子:燃油车和电车都需要”启动、停止、行驶”,如果各写一遍就是重复代码。把公共部分抽出来做成 Car(父类),两种车继承它即可:
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): passc1 = FuelCar("BMW", "X5", "黑色") # 子类不需要自己写 __init__,直接用父类的c1.start() # BMW X5 正在启动...c1.run() # BMW X5 正在行驶...子类会把父类**公共的(非私有)**属性和方法继承下来,私有的继承不到。所以父类里 self.__owner 这类私有属性,子类无法直接使用(可以先调父类的 get_owner() 取脱敏值)。
方法重写
重写是指子类继承父类后,如果父类中的方法不满足需求,可以在子类中重新定义一个同名方法,从而用子类的实现替换父类的实现。
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
多继承指的是一个子类同时继承多个父类(会把多个父类中非私有的属性和方法都继承下来)。
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)MRO:Method Resolution Order(方法解析顺序)。当一个类继承了多个父类时,默认优先使用第一个父类中的同名属性或方法;查看顺序可以用 类名.__mro__ 属性或 类名.mro() 方法。
相关
练习题
一、回忆填空(写完再展开对答案)
- 继承描述的是两个类之间的关系:子类继承父类,就能获取父类的 ____ 和 ____
- 继承的语法:
class 子类(____): - 子类能继承父类____(全部 / 只有非私有)的属性和方法
- 重写是指在子类中重新定义与父类 ____ 的方法,用子类的实现替换父类
- 在子类里调用父类方法有两种写法:
____().方法名()和____.方法名(self) - 多继承的语法:
class 子类(父类1, 父类2):;同名方法默认优先使用第 ____ 个父类的 - 查看方法解析顺序用
类名.____属性或类名.____()方法,缩写是 ____
填空答案(做完再点开)
- 属性 / 方法 2. 父类 3. 只有非私有 4. 同名 5.
super/ 父类名 6. 一 7.__mro__/mro/ MRO(Method Resolution Order,方法解析顺序)
二、裸写题
-
2-1 抽出父类 定义
Animal父类(属性 name、方法speak()),再定义Dog、Cat两个子类继承它,实例化后分别调用speak()。提示(先自己想,实在想不出再点开)一级 · 思路:公共的属性/方法放父类,子类只写
class 子类(父类): pass二级 · 方法:class Dog(Animal):三级 · 骨架:子类不用写__init__,直接用父类的 -
2-2 重写方法 让
Dog和Cat各自重写speak():狗输出”汪汪”,猫输出”喵喵”;并在子类里先用super()调用一次父类的speak()。提示一级 · 思路:写一个和父类同名的方法即可覆盖 二级 · 方法:
super().speak()三级 · 骨架:先super().speak()再打印子类特有的声音 -
2-3 多继承与 MRO 再定义一个
GuideDog(导盲犬)同时继承Dog和一个Trained类(有guide()方法),打印它的 MRO 看看顺序。提示一级 · 思路:多继承把两个父类的本事合到一个子类;用 MRO 确认同名方法用谁的 二级 · 方法:
class GuideDog(Dog, Trained):/GuideDog.__mro__三级 · 骨架:for c in GuideDog.__mro__: print(c.__name__)
参考答案(做完再点开)
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}: 喵喵~')
class Trained: def guide(self): print("正在引导主人过马路...")
class GuideDog(Dog, Trained): # 2-3:多继承 pass
d = Dog("旺财")c = Cat("咪咪")d.speak()c.speak()
g = GuideDog("豆豆")g.speak() # 用 Dog 的 speakg.guide() # 用 Trained 的 guide
for cls in GuideDog.__mro__: print(cls.__name__) # GuideDog → Dog → Animal → Trained → object评论区
如果你喜欢,那么欢迎来到我的世界!
了解更多













