多态这个词指的是函数或方法在不同上下文中采取不同形式的能力。由于 Python 是一种动态类型的语言,因此在 Python 中实现多态非常容易。
如果父类中的一个方法在其不同的子类中被覆盖并且具有不同的业务逻辑,那么这个基类方法就是一个多态方法。
在 Python 中实现多态的四种方式
实现多态
Python 中的鸭子类型
鸭子类型是一种概念,在这种概念中,对象的类型或类的重要性不如它所定义的方法。使用这一概念,只要方法存在,你就可以在不检查其类型的情况下调用任何对象的方法。
这个术语由一句著名的引言定义:假如有一只鸟走路像鸭子、游泳像鸭子、看起来像鸭子、叫起来也像鸭子,那它很可能就是一只鸭子。
示例
在下面的代码中,我们实际演示了鸭子类型的概念。
class Duck:
def sound(self):
return "Quack, quack!"
class AnotherBird:
def sound(self):
return "I'm similar to a duck!"
def makeSound(duck):
print(duck.sound())
duck = Duck()
anotherBird = AnotherBird()
makeSound(duck)
makeSound(anotherBird)
当你执行这段代码时,将产生以下输出:
Quack, quack!
I'm similar to a duck!
Python 中的方法重写
在方法重写中,子类中定义的方法与其超类中的方法同名,但实现了不同的功能。
示例
作为多态的一个例子,下面的代码中,shape
是一个抽象类。它作为两个类 circle
和 rectangle
的父类。这两个类以不同的方式重写了父类的 draw()
方法。
from abc import ABC, abstractmethod
class shape(ABC):
@abstractmethod
def draw(self):
"抽象方法"
return
class circle(shape):
def draw(self):
super().draw()
print ("画一个圆")
return
class rectangle(shape):
def draw(self):
super().draw()
print ("画一个矩形")
return
shapes = [circle(), rectangle()]
for shp in shapes:
shp.draw()
当你运行上面的代码时,会产生以下输出:
画一个圆
画一个矩形
变量 shp
首先引用 circle
对象并调用 circle
类中的 draw()
方法。在下一次迭代中,它引用 rectangle
对象并调用 rectangle
类中的 draw()
方法。因此,shape
类中的 draw()
方法是多态的。
Python 中的运算符重载
假设你创建了一个 Vector
类来表示二维向量,当你使用加号运算符来相加它们时会发生什么?很可能 Python 会报错。
然而,你可以在你的类中定义 __add__
方法来执行向量加法,这样加号运算符就会按预期工作。
示例
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
def __add__(self,other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)
当执行上面的代码时,会产生以下结果:
Vector(7,8)
Python 中的方法重载
当一个类包含两个或更多具有相同名称但参数数量不同的方法时,这种情况可以称为方法重载。
Python 默认不允许方法重载,但是我们可以使用变长参数列表、多重分发以及默认参数等技术来实现这一点。
示例
在下面的示例中,我们使用变长参数列表来实现方法重载。
def add(*nums):
return sum(nums)
result1 = add(10, 25)
result2 = add(10, 25, 35)
print(result1)
print(result2)
当执行上面的代码时,会产生以下结果:
35
70