Python 继承与多态
目录
学习目标
- 理解继承的概念和作用
- 掌握单继承和多继承的用法
- 理解
super()的作用和使用方法 - 掌握方法重写和多态的实现
一、继承基础
继承是面向对象编程的核心特性之一,允许一个类(子类)继承另一个类(父类)的属性和方法。
# 父类(基类)
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return f"{self.name} 发出声音"
def move(self):
return f"{self.name} 在移动"
# 子类(派生类)
class Dog(Animal):
def speak(self):
return f"{self.name} 说: 汪汪!"
class Cat(Animal):
def speak(self):
return f"{self.name} 说: 喵喵!"
# 使用
dog = Dog("Buddy")
cat = Cat("Luna")
print(dog.speak()) # Buddy 说: 汪汪!
print(cat.speak()) # Luna 说: 喵喵!
print(dog.move()) # Buddy 在移动(继承自 Animal)二、super() 函数
super() 用于调用父类的方法,常用于在子类中扩展父类的功能。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
return f"我是 {self.name},{self.age} 岁"
class Student(Person):
def __init__(self, name, age, grade):
# 调用父类的 __init__
super().__init__(name, age)
self.grade = grade
def introduce(self):
# 调用父类的 introduce 并扩展
base = super().introduce()
return f"{base},我在 {self.grade} 年级"
s = Student("Alice", 15, "初三")
print(s.introduce())
# 我是 Alice,15 岁,我在 初三年级三、方法重写
子类可以重写(覆盖)父类的方法,以提供特定的实现。
class Shape:
def __init__(self, name):
self.name = name
def area(self):
raise NotImplementedError("子类必须实现 area 方法")
def perimeter(self):
raise NotImplementedError("子类必须实现 perimeter 方法")
def info(self):
return f"{self.name}: 面积={self.area():.2f}, 周长={self.perimeter():.2f}"
class Rectangle(Shape):
def __init__(self, width, height):
super().__init__("矩形")
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
class Circle(Shape):
PI = 3.14159
def __init__(self, radius):
super().__init__("圆形")
self.radius = radius
def area(self):
return self.PI * self.radius ** 2
def perimeter(self):
return 2 * self.PI * self.radius
# 使用
rect = Rectangle(5, 3)
circle = Circle(4)
print(rect.info()) # 矩形: 面积=15.00, 周长=16.00
print(circle.info()) # 圆形: 面积=50.27, 周长=25.13四、多态
多态是指同一个方法调用,作用于不同的对象,产生不同的行为。
class Animal:
def speak(self):
return "动物发出声音"
class Dog(Animal):
def speak(self):
return "汪汪!"
class Cat(Animal):
def speak(self):
return "喵喵!"
class Duck(Animal):
def speak(self):
return "嘎嘎!"
# 多态:统一的接口,不同的行为
def animal_concert(animals):
for animal in animals:
print(f"{type(animal).__name__}: {animal.speak()}")
# 创建不同的动物
animals = [Dog(), Cat(), Duck()]
animal_concert(animals)
# Dog: 汪汪!
# Cat: 喵喵!
# Duck: 嘎嘎!
# Python 的鸭子类型
def make_it_speak(obj):
"""只要有 speak 方法就行,不需要继承关系"""
print(obj.speak())
class Robot:
def speak(self):
return "哔哔啵啵"
make_it_speak(Dog()) # 汪汪!
make_it_speak(Robot()) # 哔哔啵啵五、多继承
Python 支持多继承,一个子类可以继承多个父类。
class Flyable:
def fly(self):
return "我能飞"
class Swimmable:
def swim(self):
return "我能游泳"
class Duck(Flyable, Swimmable):
def speak(self):
return "嘎嘎"
duck = Duck()
print(duck.fly()) # 我能飞
print(duck.swim()) # 我能游泳
print(duck.speak()) # 嘎嘎MRO(方法解析顺序)
当多继承出现同名方法时,Python 使用 C3 线性化算法确定调用顺序。
class A:
def method(self):
return "A"
class B(A):
def method(self):
return "B"
class C(A):
def method(self):
return "C"
class D(B, C):
pass
d = D()
print(d.method()) # B(按 MRO 顺序)
# 查看 MRO
print(D.__mro__)
# (<class 'D'>, <class 'B'>, <class 'C'>, <class 'A'>, <class 'object'>)
# 使用 super() 按 MRO 调用
class E(B, C):
def method(self):
return f"E -> {super().method()}"
e = E()
print(e.method()) # E -> B菱形继承问题
class A:
def __init__(self):
print("A.__init__")
self.a = "a"
class B(A):
def __init__(self):
print("B.__init__")
super().__init__() # 使用 super 避免重复调用
self.b = "b"
class C(A):
def __init__(self):
print("C.__init__")
super().__init__()
self.c = "c"
class D(B, C):
def __init__(self):
print("D.__init__")
super().__init__()
self.d = "d"
d = D()
# D.__init__
# B.__init__
# C.__init__
# A.__init__
# A 只被调用一次!
print(d.a, d.b, d.c, d.d) # a b c d六、isinstance 和 issubclass
class Animal:
pass
class Dog(Animal):
pass
dog = Dog()
# isinstance:检查对象是否是指定类的实例
print(isinstance(dog, Dog)) # True
print(isinstance(dog, Animal)) # True(继承关系)
print(isinstance(dog, object)) # True(所有类都继承 object)
# issubclass:检查类是否是另一个类的子类
print(issubclass(Dog, Animal)) # True
print(issubclass(Dog, object)) # True
print(issubclass(Animal, Dog)) # False七、抽象基类
抽象基类(Abstract Base Class, ABC)定义了接口规范,子类必须实现指定的方法。
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
"""计算面积"""
pass
@abstractmethod
def perimeter(self):
"""计算周长"""
pass
def info(self):
return f"面积={self.area()}, 周长={self.perimeter()}"
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
# shape = Shape() # TypeError: 不能实例化抽象类
rect = Rectangle(5, 3)
print(rect.info()) # 面积=15, 周长=16八、综合示例
"""
员工管理系统 - 继承与多态应用
"""
from abc import ABC, abstractmethod
class Employee(ABC):
"""员工基类"""
def __init__(self, name, employee_id):
self.name = name
self.employee_id = employee_id
@abstractmethod
def calculate_salary(self):
"""计算薪资(子类必须实现)"""
pass
def info(self):
return f"{self.name} ({self.employee_id}) - 月薪: {self.calculate_salary():.2f}"
class SalariedEmployee(Employee):
"""固定薪资员工"""
def __init__(self, name, employee_id, monthly_salary):
super().__init__(name, employee_id)
self.monthly_salary = monthly_salary
def calculate_salary(self):
return self.monthly_salary
class HourlyEmployee(Employee):
"""时薪员工"""
def __init__(self, name, employee_id, hourly_rate, hours_worked):
super().__init__(name, employee_id)
self.hourly_rate = hourly_rate
self.hours_worked = hours_worked
def calculate_salary(self):
return self.hourly_rate * self.hours_worked
class CommissionEmployee(Employee):
"""佣金员工"""
def __init__(self, name, employee_id, base_salary, sales, commission_rate):
super().__init__(name, employee_id)
self.base_salary = base_salary
self.sales = sales
self.commission_rate = commission_rate
def calculate_salary(self):
return self.base_salary + self.sales * self.commission_rate
# 创建员工列表(多态)
employees = [
SalariedEmployee("Alice", "E001", 15000),
HourlyEmployee("Bob", "E002", 100, 160),
CommissionEmployee("Charlie", "E003", 8000, 50000, 0.1),
]
# 统一处理(多态)
print("=" * 50)
print(" 员 工 薪 资 报 表")
print("=" * 50)
for emp in employees:
print(emp.info())
# 计算总薪资
total = sum(emp.calculate_salary() for emp in employees)
print("=" * 50)
print(f"总薪资支出: {total:.2f}")小结
- 继承使用
class Child(Parent)语法,子类继承父类的属性和方法 super()调用父类方法,常用于扩展构造方法- 方法重写让子类提供特定实现,实现多态
- Python 支持多继承,使用 MRO 确定方法调用顺序
- 抽象基类(ABC)定义接口规范,子类必须实现抽象方法
isinstance()检查对象类型,issubclass()检查继承关系
练习
- 定义一个
Vehicle基类,再定义Car和Bicycle子类,重写move()方法。 - 使用
super()在子类中扩展父类的__init__方法。 - 创建一个抽象基类
Payment,定义pay(amount)抽象方法,然后实现Alipay和WechatPay子类。 - 分析以下多继承的 MRO 输出:
class A: pass class B(A): pass class C(A): pass class D(B, C): pass print(D.__mro__) - 解释 Python 的"鸭子类型",并举例说明。