一、什么是继承?
继承(Inheritance) 是面向对象编程的三大特性之一(封装、继承、多态)。它允许我们创建一个新类(称为子类或派生类),从一个或多个现有类(称为父类或基类)中继承属性和方法,从而实现代码复用和扩展。
classAnimal: # 父类
defeat(self):
print("吃东西")
classDog(Animal): # 子类,继承 Animal
defbark(self):
print("汪汪叫")
dog = Dog()
dog.eat() # 继承自父类:吃东西
dog.bark() # 子类自己的方法:汪汪叫
二、为什么使用继承?
- • 代码复用:子类可以直接使用父类已有的属性和方法,避免重复编写。
- • 层次化设计:通过继承建立类之间的层次关系,更符合现实世界的分类。
- • 可扩展性:在父类基础上添加新功能,或修改已有行为(方法重写)。
三、单继承的基本语法
class子类名(父类名):
# 子类的属性和方法
示例:学生和教师继承自人类
classPerson:
def__init__(self, name, age):
self.name = name
self.age = age
defintroduce(self):
print(f"我叫{self.name},今年{self.age}岁")
classStudent(Person):
def__init__(self, name, age, student_id):
super().__init__(name, age) # 调用父类的 __init__
self.student_id = student_id
defstudy(self):
print(f"{self.name} 正在学习")
classTeacher(Person):
def__init__(self, name, age, subject):
super().__init__(name, age)
self.subject = subject
defteach(self):
print(f"{self.name} 正在教 {self.subject}")
# 使用
stu = Student("张三", 18, "S001")
stu.introduce() # 我叫张三,今年18岁
stu.study() # 张三 正在学习
tea = Teacher("李老师", 35, "数学")
tea.introduce() # 我叫李老师,今年35岁
tea.teach() # 李老师 正在教 数学
四、方法重写(Override)
子类可以重新定义父类中已有的方法,称为方法重写。重写后,子类实例调用该方法时会执行子类的版本。
classAnimal:
defsound(self):
print("动物发出声音")
classCat(Animal):
defsound(self): # 重写父类的 sound 方法
print("喵喵喵")
classDog(Animal):
defsound(self): # 重写父类的 sound 方法
print("汪汪汪")
animals = [Cat(), Dog(), Animal()]
for a in animals:
a.sound()
# 输出:
# 喵喵喵
# 汪汪汪
# 动物发出声音
五、super() 函数
super() 用于在子类中调用父类的方法,特别是在 __init__ 中初始化父类的属性,或在重写的方法中保留父类的行为。
classVehicle:
def__init__(self, brand):
self.brand = brand
definfo(self):
print(f"品牌: {self.brand}")
classCar(Vehicle):
def__init__(self, brand, model):
super().__init__(brand) # 调用父类的 __init__
self.model = model
definfo(self):
super().info() # 调用父类的 info
print(f"型号: {self.model}")
car = Car("特斯拉", "Model 3")
car.info()
# 输出:
# 品牌: 特斯拉
# 型号: Model 3
六、属性查找顺序
当访问一个属性或方法时,Python 会按照以下顺序查找:
- 3. 父类的
__dict__(按照 MRO 顺序) - 4. 继续向上查找,直到找到或抛出 AttributeError
classA:
value = "A的类属性"
classB(A):
value = "B的类属性"
classC(B):
pass
c = C()
print(c.value) # B的类属性(在 B 中找到,不再向上)
七、isinstance() 与 issubclass()
- •
isinstance(obj, Class):判断一个对象是否是某个类(或其父类)的实例。 - •
issubclass(Sub, Parent):判断一个类是否是另一个类的子类。
classAnimal: pass
classDog(Animal): pass
classCat(Animal): pass
dog = Dog()
print(isinstance(dog, Dog)) # True
print(isinstance(dog, Animal)) # True(Dog 是 Animal 的子类)
print(isinstance(dog, Cat)) # False
print(issubclass(Dog, Animal)) # True
print(issubclass(Dog, object)) # True(所有类都继承自 object)
八、实战案例
8.1 图形类层次
import math
classShape:
"""图形基类"""
defarea(self):
pass
defperimeter(self):
pass
classRectangle(Shape):
def__init__(self, width, height):
self.width = width
self.height = height
defarea(self):
returnself.width * self.height
defperimeter(self):
return2 * (self.width + self.height)
classCircle(Shape):
def__init__(self, radius):
self.radius = radius
defarea(self):
return math.pi * self.radius ** 2
defperimeter(self):
return2 * math.pi * self.radius
shapes = [Rectangle(4, 5), Circle(3)]
for s in shapes:
print(f"面积: {s.area():.2f}, 周长: {s.perimeter():.2f}")
8.2 员工管理系统
classEmployee:
def__init__(self, name, salary):
self.name = name
self.salary = salary
defwork(self):
print(f"{self.name} 正在工作")
defget_annual_salary(self):
returnself.salary * 12
classManager(Employee):
def__init__(self, name, salary, bonus):
super().__init__(name, salary)
self.bonus = bonus
defwork(self):
print(f"{self.name} 正在管理团队")
defget_annual_salary(self):
returnsuper().get_annual_salary() + self.bonus
classDeveloper(Employee):
def__init__(self, name, salary, language):
super().__init__(name, salary)
self.language = language
defwork(self):
print(f"{self.name} 正在用 {self.language} 编写代码")
employees = [
Manager("张三", 15000, 30000),
Developer("李四", 12000, "Python"),
Employee("王五", 8000)
]
for e in employees:
e.work()
print(f"年薪: {e.get_annual_salary()}")
九、注意事项
- 1. 所有类都继承自
object:在 Python 3 中,如果没有指定父类,类会隐式继承 object。 - 2. 子类的
__init__ 必须调用 super().__init__:否则父类的属性不会被初始化(除非父类的 __init__ 为空)。 - 3. 方法重写时,
super() 可以调用父类版本,既保留父类行为又添加新功能。 - 4. 避免过深的继承层次:继承层次过深会降低代码可读性和可维护性,优先考虑组合。
- 5. 子类可以访问父类的公有和受保护成员,但不能直接访问私有成员(双下划线开头的名称会被修饰)。
十、总结
- • 继承 允许子类复用父类的属性和方法,是代码复用的重要手段。
- •
super() 用于在子类中调用父类的方法,特别是在 __init__ 中。 - •
isinstance() 和 issubclass() 用于类型判断。 - • 继承建立了类之间的“is-a”关系(如 Dog is an Animal)。
继承是面向对象编程的核心,掌握单继承是理解更复杂的多继承和 mixin 模式的基础。合理使用继承可以让你的代码更加简洁、可扩展。