在python的面向对象编程体系中,子类继承父类后,不需要重新编写父类已经实现的功能,通过合理的方式可以直接重用父类的属性和方法,这是面向对象编程代码复用特性的核心体现。掌握子类重用父类功能的方法,能有效减少冗余代码,提升程序的可维护性。

直接调用父类的方式
如果父类的方法不需要重写,子类可以直接通过父类名.方法名(self, 参数)的方式调用父类的功能,这种方式逻辑直观,适合简单的继承场景。
基础示例
首先定义一个父类Animal,包含属性和方法:
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
print(f"{self.name} 正在吃东西")
def sleep(self):
print(f"{self.name} 正在睡觉")
定义子类Dog继承Animal,直接调用父类的eat和sleep方法:
class Dog(Animal):
def bark(self):
# 直接调用父类的eat方法
Animal.eat(self)
print(f"{self.name} 还在叫")
# 实例化子类对象
dog = Dog("小黑")
dog.bark()
dog.sleep()
运行上述代码,输出结果为:
小黑 正在吃东西 小黑 还在叫 小黑 正在睡觉
注意事项
- 直接调用父类方法时,必须显式传入
self参数,否则会报参数缺失的错误 - 如果父类名发生修改,所有直接调用父类的地方都需要同步修改,维护成本较高
使用super函数调用父类
super()函数是python中专门用于调用父类方法的工具,它会自动处理父类的查找逻辑,不需要显式传入self参数,是更推荐的调用方式。
基本用法
同样使用上面的Animal父类,子类Cat使用super()调用父类方法:
class Cat(Animal):
def __init__(self, name, color):
# 调用父类的__init__方法初始化name属性
super().__init__(name)
self.color = color
def play(self):
# 调用父类的eat方法
super().eat()
print(f"这是一只{self.color}的猫")
# 实例化子类对象
cat = Cat("小白", "白色")
cat.play()
cat.sleep()
运行结果为:
小白 正在吃东西 这是一只白色的猫 小白 正在睡觉
super函数的优势
- 不需要显式传入
self参数,代码更简洁 - 遵循方法解析顺序(MRO),在多重继承场景下能正确找到对应的父类方法
- 父类名修改时,不需要修改子类中的调用逻辑,维护更方便
子类重写父类方法后重用父类功能
如果子类需要重写父类的方法,又想保留父类方法的原有逻辑,可以在重写的方法中先调用父类的对应方法,再添加子类特有的逻辑。
示例演示
父类Shape有计算面积的方法,子类Circle重写该方法,先调用父类的校验逻辑,再计算圆的面积:
class Shape:
def __init__(self, radius):
if radius <= 0:
raise ValueError("半径必须大于0")
self.radius = radius
def area(self):
# 父类的基础面积计算逻辑
pass
class Circle(Shape):
def area(self):
# 先调用父类的__init__方法完成参数校验
super().__init__(self.radius)
# 再添加子类特有的面积计算逻辑
import math
return math.pi * self.radius ** 2
# 测试代码
circle = Circle(5)
print(f"圆的面积是: {circle.area():.2f}")
运行结果为:
圆的面积是: 78.54
不同调用方式的适用场景
为了更清晰地选择调用方式,以下是两种方式的对比:
| 调用方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 父类名.方法名(self) | 单继承、父类逻辑简单、不需要频繁修改父类名 | 逻辑直观,容易理解 | 需要显式传self,父类名修改时需要同步修改所有调用处 |
| super() | 单继承、多重继承、需要降低维护成本 | 无需传self,遵循MRO,维护方便 | 多重继承场景下需要理解MRO逻辑 |
常见问题说明
问:super()函数只能在子类中调用父类方法吗?
答:super()函数不仅可以调用父类的方法,还可以调用父类的属性,使用方式和调用方法一致,例如super().属性名即可获取父类的对应属性。
问:多重继承时super()调用的是哪个父类的方法?
答:super()会按照类的MRO顺序查找父类,MRO顺序可以通过类名.__mro__查看,调用时会找到MRO中当前类的下一个类的方法执行。