写 Python 时,经常要处理相似但又有差别的对象。比如你有个 Animal 类,它有名字、会叫;然后你想造出 Dog 和 Cat,它们都算动物,但叫声不同、行为也略有区别——这时候,类继承就派上用场了。
最基础的继承:子类复用父类属性和方法
先看一个最简单的例子:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name} 发出声音")
class Dog(Animal):
pass
my_dog = Dog("旺财")
my_dog.speak() # 输出:旺财 发出声音
这里 Dog 继承自 Animal,没写任何新东西,但自动拥有了 __init__ 和 speak 方法。就像孩子自然继承了父母的基本特征。
重写方法:让狗“汪汪”,猫“喵喵”
如果所有动物都只会说“发出声音”,那太无聊了。我们让子类按需改写 speak:
class Cat(Animal):
def speak(self):
print(f"{self.name} 喵喵叫")
my_cat = Cat("咪咪")
my_cat.speak() # 输出:咪咪 喵喵叫
这种“父类定义接口,子类实现细节”的方式,正是面向对象里多态的体现。
扩展功能:给狗加个“摇尾巴”动作
子类不仅能改,还能加新东西:
class Dog(Animal):
def speak(self):
print(f"{self.name} 汪汪汪!")
def wag_tail(self):
print(f"{self.name} 开心地摇尾巴")
my_dog = Dog("大黄")
my_dog.speak() # 输出:大黄 汪汪汪!
my_dog.wag_tail() # 输出:大黄 开心地摇尾巴
注意:Dog 仍能调用 Animal 的 name 属性,说明继承不是复制粘贴,而是建立了一条可追溯的“关系链”。
调用父类方法:初始化时别漏掉基础设置
如果子类自己写了 __init__,又想保留父类的初始化逻辑,得手动调用 super():
class Bird(Animal):
def __init__(self, name, wing_span):
super().__init__(name) # 先让 Animal 设置 name
self.wing_span = wing_span
def fly(self):
print(f"{self.name} 展开 {self.wing_span} 米翅膀起飞")
my_bird = Bird("小羽", 1.2)
print(my_bird.name) # 输出:小羽
my_bird.fly() # 输出:小羽 展开 1.2 米翅膀起飞
不写 super().__init__(name),self.name 就压根不存在——这就像孩子忘了登记户口,连名字都没法用。
多重继承?先少碰,够用就行
Python 支持一个类继承多个父类(比如 class RobotDog(Dog, Robot)),但初学容易绕晕。日常开发中,单继承 + 明确职责划分,已经能解决 90% 的问题。真遇到复杂场景,再研究 MRO(方法解析顺序)也不迟。
类继承不是炫技,是帮代码更贴近现实关系。写的时候多想想:这个“是不是那个”的关系成立吗?成立,就放心继承;不成立,硬套反而埋坑。