一、什么是多态?
多态(Polymorphism) 是面向对象编程的三大特性之一(封装、继承、多态)。它指的是同一个方法或操作,作用于不同的对象时,可以产生不同的行为结果。
简单来说:多态允许你用一个统一的接口(如方法名)来调用不同类型的对象,而每个对象会根据自身的类型给出相应的实现。
classDog:
defsound(self):
print("汪汪汪")
classCat:
defsound(self):
print("喵喵喵")
defmake_sound(animal):
animal.sound() # 统一的调用接口
make_sound(Dog()) # 汪汪汪
make_sound(Cat()) # 喵喵喵
二、为什么需要多态?
- • 代码复用:编写通用的函数或类,可以处理多种不同类型的对象。
- • 松耦合:调用方不需要知道对象的具体类型,只需要知道对象支持某个方法即可。
- • 可扩展性:增加新类型时,无需修改已有的通用代码,只要新类型实现了约定好的接口。
三、Python 中的多态实现方式
Python 的多态是**“鸭子类型(Duck Typing)”** 风格的:只要一个对象“看起来像鸭子,叫起来像鸭子”,那它就是鸭子。Python 不关心对象的类型,只关心对象是否具有所需的方法或属性。
3.1 继承多态
通过继承和方法重写实现多态是最传统的方式。
classAnimal:
defsound(self):
raise NotImplementedError("子类必须实现 sound 方法")
classDog(Animal):
defsound(self):
print("汪汪汪")
classCat(Animal):
defsound(self):
print("喵喵喵")
defanimal_sound(animal):
animal.sound()
animals = [Dog(), Cat()]
for a in animals:
animal_sound(a)
3.2 鸭子类型(Duck Typing)
Python 不强制要求继承关系,只要对象有相应的方法,就可以被多态地调用。
classBird:
deffly(self):
print("鸟儿在飞")
classAirplane:
deffly(self):
print("飞机在飞")
classSuperman:
deffly(self):
print("超人在飞")
defmake_it_fly(obj):
obj.fly() # 不关心 obj 是什么类型,只要它有 fly 方法
make_it_fly(Bird()) # 鸟儿在飞
make_it_fly(Airplane()) # 飞机在飞
make_it_fly(Superman()) # 超人在飞
四、多态与抽象基类
Python 的 abc 模块可以定义抽象基类,强制子类实现某些方法,从而实现更规范的多态。
from abc import ABC, abstractmethod
classShape(ABC):
@abstractmethod
defarea(self):
"""计算面积,子类必须实现"""
pass
classRectangle(Shape):
def__init__(self, width, height):
self.width = width
self.height = height
defarea(self):
returnself.width * self.height
classCircle(Shape):
def__init__(self, radius):
self.radius = radius
defarea(self):
return3.14159 * self.radius ** 2
defprint_area(shape):
print(f"面积: {shape.area()}")
shapes = [Rectangle(4, 5), Circle(3)]
for s in shapes:
print_area(s)
五、多态在 Python 内置类型中的体现
Python 的内置函数和操作符本身就是多态的典范:
5.1 len() 函数
len() 可以作用于字符串、列表、元组、字典等多种类型。
print(len("hello")) # 5
print(len([1, 2, 3])) # 3
print(len({"a": 1, "b": 2})) # 2
5.2 + 运算符
+ 可以用于数字相加、字符串拼接、列表合并。
print(3 + 5) # 8(数字相加)
print("Hello" + " " + "World") # Hello World(字符串拼接)
print([1, 2] + [3, 4]) # [1, 2, 3, 4](列表合并)
5.3 for 循环
for 循环可以遍历任何可迭代对象(实现了 __iter__ 方法的对象)。
for x in"abc":
print(x)
for x in [1, 2, 3]:
print(x)
for x in {"a": 1, "b": 2}:
print(x)
六、多态与接口
在静态类型语言中,多态通常通过接口(interface)实现。Python 虽然没有显式的接口关键字,但可以通过鸭子类型或抽象基类达到类似效果。
6.1 使用鸭子类型(隐式接口)
classUSBDevice:
defconnect(self):
print("USB 设备已连接")
classBluetoothDevice:
defconnect(self):
print("蓝牙设备已连接")
defconnect_device(device):
device.connect() # 任何有 connect 方法的对象都可以传入
connect_device(USBDevice())
connect_device(BluetoothDevice())
6.2 使用抽象基类(显式接口)
from abc import ABC, abstractmethod
classConnectable(ABC):
@abstractmethod
defconnect(self):
pass
classMouse(Connectable):
defconnect(self):
print("鼠标已连接")
classKeyboard(Connectable):
defconnect(self):
print("键盘已连接")
defconnect_device(device: Connectable):
device.connect()
七、实战案例
7.1 支付系统(不同支付方式)
classPayment:
defpay(self, amount):
raise NotImplementedError
classAlipay(Payment):
defpay(self, amount):
print(f"使用支付宝支付 {amount} 元")
classWechatPay(Payment):
defpay(self, amount):
print(f"使用微信支付 {amount} 元")
classCreditCard(Payment):
defpay(self, amount):
print(f"使用信用卡支付 {amount} 元")
defcheckout(payment_method, amount):
payment_method.pay(amount)
checkout(Alipay(), 100)
checkout(WechatPay(), 200)
checkout(CreditCard(), 50)
7.2 通知系统
classNotifier:
defsend(self, message):
raise NotImplementedError
classEmailNotifier(Notifier):
defsend(self, message):
print(f"发送邮件: {message}")
classSMSNotifier(Notifier):
defsend(self, message):
print(f"发送短信: {message}")
classPushNotifier(Notifier):
defsend(self, message):
print(f"推送通知: {message}")
defnotify_all(notifiers, message):
for n in notifiers:
n.send(message)
notifiers = [EmailNotifier(), SMSNotifier(), PushNotifier()]
notify_all(notifiers, "系统维护通知")
7.3 自定义迭代器(实现多态的 __iter__)
classMyRange:
def__init__(self, start, end):
self.start = start
self.end = end
def__iter__(self):
current = self.start
while current < self.end:
yield current
current += 1
classMyList:
def__init__(self, items):
self.items = items
def__iter__(self):
returniter(self.items)
defprint_all(iterable):
for item in iterable:
print(item)
print_all(MyRange(1, 5))
print_all(MyList(["a", "b", "c"]))
八、多态与类型提示
Python 的类型提示(Type Hints)可以帮助表达多态接口,但 Python 本身并不强制检查。
from typing import Protocol
classFlyable(Protocol):
deffly(self) -> None:
...
classBird:
deffly(self) -> None:
print("鸟飞")
classAirplane:
deffly(self) -> None:
print("飞机飞")
defmake_fly(obj: Flyable) -> None:
obj.fly()
make_fly(Bird())
make_fly(Airplane())
使用 Protocol(Python 3.8+)可以定义结构化的子类型(类似于 Go 的接口)。
九、总结
- • 多态 允许同一操作作用于不同对象时产生不同行为。
- • Python 的多态是基于鸭子类型的:不关心对象类型,只关心对象是否有需要的方法或属性。
- • 抽象基类(
abc.ABC + @abstractmethod)可以强制子类实现特定方法,实现更规范的多态。 - • Python 内置函数(如
len()、print())和运算符(如 +、*)都体现了多态思想。
核心思想:面向接口编程,而不是面向实现编程。多态让代码更灵活、更可扩展,是设计可维护系统的关键。
掌握多态,是写出高质量、可扩展 Python 代码的重要一步。它让你可以用统一的接口处理多种不同的对象,而不需要关心具体的类型。