基础:单继承
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} 发出声音")
class Dog(Animal): # 继承 Animal
def speak(self): # 覆盖父类方法
print(f"{self.name} 汪汪")
class Cat(Animal):
def speak(self):
print(f"{self.name} 喵喵")
for animal in [Dog("Rex"), Cat("Mimi"), Animal("XX")]:
animal.speak()
# Rex 汪汪
# Mimi 喵喵
# XX 发出声音
多态:同一段代码(animal.speak())对不同类型有不同行为。
super():调用父类方法
子类想"在父类基础上加点料":
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # 先让父类初始化
self.breed = breed
d = Dog("Rex", "柴犬")
print(d.name, d.breed)
isinstance / issubclass
isinstance(Dog("Rex"), Dog) # True
isinstance(Dog("Rex"), Animal) # True Dog 是 Animal 的子类
issubclass(Dog, Animal) # True
写函数时优先 isinstance 而不是 type(x) == X——前者支持子类。
多继承(慎用)
class Swimmer:
def swim(self):
print(f"{self.name} 在游")
class Flyer:
def fly(self):
print(f"{self.name} 在飞")
class Duck(Animal, Swimmer, Flyer):
pass
d = Duck("Donald")
d.speak() # Donald 发出声音
d.swim() # Donald 在游
d.fly() # Donald 在飞
MRO:方法解析顺序
多继承时方法找谁?看 MRO:
class A:
def hello(self): print("A")
class B(A):
def hello(self): print("B")
class C(A):
def hello(self): print("C")
class D(B, C):
pass
D().hello() # B
print(D.__mro__)
# (D, B, C, A, object)
Python 用 C3 线性化算法——简单理解:左边的父类优先,但跳过共同祖先重复。
super() 的真相
super() 不一定调"直接父类"——它按 MRO 走下一个:
class B(A):
def hello(self):
super().hello() # 在 D 的 MRO 里,super() 是 C 不是 A
print("B")
理解这点对设计 mixin 很重要。
继承的"陷阱":何时不该继承
# 反例:用继承复用代码
class List(list): # 想给 list 加点功能
def first(self):
return self[0]
子类化内置类型很容易踩坑。优先组合(持有对象) over 继承(继承对象):
class MyList:
def __init__(self):
self._data = [] # 内部持有 list
def first(self):
return self._data[0]
"继承表达类型关系,不是为了省代码"
经验法则:
- "Dog 是 Animal" → 继承
- "Engine 属于 Car" → 组合(持有对象)
下一篇讲抽象基类 ABC 与 Protocol——把"鸭子类型"形式化。