在 Python 中,多态(Polymorphism)是 “面向对象编程(OOP)” 的三大特性之一,另外两个是封装和继承。多态指的是同一个方法在不同的对象上,可能会有不同的行为。简单来说就是:一个接口,多种实现。
Python 多态是什么?
在了解多态之前,我们先来回顾一下 Python 中的 “继承”。继承允许我们定义一个基类,然后其他类(派生类)可以继承这个基类,并获得基类的属性和方法。而多态则是在继承的基础上,允许不同的派生类对同一方法有不同的实现。
举个简单例子,我们有一个 “动物” 的基类,它有一个 speak() 方法。对于不同的动物来说,speak() 方法会有不同的行为,比如:狗会 “汪汪叫”,猫会 “喵喵叫”,鸭子会 “嘎嘎叫”。speak() 方法根据调用的对象不同,表现出不同的行为,这就是多态的体现。

Python 多态的实现
Python 是一种动态类型语言,它天然支持多态。我们不需要像 Java 或 C++ 那样显式地声明接口或虚函数。只要对象拥有相同的方法名,就可以实现多态。
示例 1:Python 实现简单多态
class Animal:
def speak(self):
print('动物发出声音')
class Dog(Animal):
def speak(self):
print('汪汪叫')
class Cat(Animal):
def speak(self):
print('喵喵叫')
class Duck(Animal):
def speak(self):
print('嘎嘎叫')
# 定义一个函数,接受 Animal 类型的对象
def make_animal_speak(animal):
animal.speak()
# 创建不同动物的对象
dog = Dog()
cat = Cat()
duck = Duck()
animal = Animal()
# 调用函数,传入不同类型的动物对象
make_animal_speak(animal)
make_animal_speak(dog)
make_animal_speak(cat)
make_animal_speak(duck)运行结果如下。
动物发出声音
汪汪叫
喵喵叫
嘎嘎叫分析:
在这个例子中,我们定义了一个 Animal 基类,它有一个 speak() 方法。Dog、Cat 和 Duck 这 3 个类都继承自 Animal,并且都重写了 speak() 方法,提供了各自特定的实现。
然后,我们定义了一个 make_animal_speak() 函数,它接受一个 animal 参数。在这个函数内部,我们调用 animal.speak()。
当传入 Dog、Cat 或 Duck 的实例时,make_animal_speak() 函数会根据实际传入对象的类型,来调用其对应的 speak() 方法。
上面例子体现的就是多态。在同一个 make_animal_speak() 函数,对于不同的对象会表现出不同的行为。
Python 多态的应用
多态在实际开发中非常有用,它能够提高代码的灵活性、可扩展性和可维护性。
示例 2:处理不同类型的支付方式
class Payment:
def pay(self, amount):
raise NotImplementedError('子类必须实现 pay() 方法')
class Alipay(Payment):
def pay(self, amount):
print(f'支付宝支付 {amount} 元')
class WechatPay(Payment):
def pay(self, amount):
print(f'微信支付 {amount} 元')
class BankCardPay(Payment):
def pay(self, amount):
print(f'银行卡支付 {amount} 元')
def process_payment(payment_method, amount):
payment_method.pay(amount)
alipay = Alipay()
wechat_pay = WechatPay()
bank_card_pay = BankCardPay()
process_payment(alipay, 100)
process_payment(wechat_pay, 50)
process_payment(bank_card_pay, 200)运行结果如下。
支付宝支付 100 元
微信支付 50 元
银行卡支付 200 元分析:
假设我们正在开发一个电商平台,需要处理多种支付方式(如支付宝、微信支付、银行卡支付)。我们可以定义一个统一的支付接口,然后每种支付方式都实现这个接口。
在这个例子中,Payment 类定义了一个 pay() 方法的接口(虽然 Python 没有严格的接口定义,但 NotImplementedError 强制子类实现)。Alipay、WechatPay 和 BankCardPay 这 3 个类都继承 Payment 类,并实现了自己的 pay() 方法。
process_payment() 函数可以接受任何 Payment 类型的对象,并调用其 pay() 方法,从而实现不同支付方式的统一处理。
示例 3:多态实现 “绘制图形”
import math
class Shape:
def area(self):
raise NotImplementedError('子类必须实现 area() 方法')
def draw(self):
raise NotImplementedError('子类必须实现 draw() 方法')
# 绘制圆形
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return math.pi * self.radius ** 2
def draw(self):
print(f'绘制圆形,半径为 {self.radius},面积为 {self.area():.2f}')
# 绘制矩形
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def draw(self):
print(f'绘制矩形,宽度为 {self.width},高度为 {self.height},面积为 {self.area():.2f}')
def render_shape(shape):
shape.draw()
circle = Circle(5)
rectangle = Rectangle(4, 6)
render_shape(circle)
render_shape(rectangle)运行结果如下。
绘制圆形,半径为 5,面积为 78.54
绘制矩形,宽度为 4,高度为 6,面积为 24.00分析:
在 Shape 类中,我们定义了 area() 和 draw() 方法作为图形的通用接口。Circle 和 Rectangle 分别实现了这些方法,提供了各自形状的计算面积和绘制逻辑。
render_shape() 函数可以处理任何 Shape 类型的对象,并调用其 draw() 方法,从而实现了不同图形的统一绘制。
