Python 多态(polymorphism)
多态指:同一套接口(如同一方法名、同一函数调用形式)作用于不同类型的对象时,可以表现出各自不同的行为。调用方往往只关心「有没有这个方法」,而不必写死具体类型。
在 Python 中,多态常与鸭子类型一起出现:不强制继承同一父类,只要对象实现了所需方法即可。与 OOP 总览见 面向对象编程;继承与方法重写见 类的继承、多重继承;运算符侧见 运算符重载。
鸭子类型:不同类,同一调用方式
下面 Rabbit 与 Horse 都有 age()、color(),可以放在同一循环里调用,而无需判断类型:
python
class Rabbit:
def age(self):
print("计算兔子的年龄。")
def color(self):
print("计算兔子的颜色。")
class Horse:
def age(self):
print("计算马的年龄。")
def color(self):
print("计算马的颜色。")
obj1 = Rabbit()
obj2 = Horse()
for creature in (obj1, obj2):
creature.age()
creature.color()注意:循环变量不要用 type,以免遮蔽内置函数 type()。
输出:
text
计算兔子的年龄。
计算兔子的颜色。
计算马的年龄。
计算马的颜色。继承与方法重写
子类定义与父类同名的方法会重写父类实现;通过父类引用或统一接口调用时,实际执行的是对象真实类型上的方法,这是经典 OOP 多态。
python
class Animal:
def kind(self):
print("各种动物。")
def age(self):
print("动物的年龄(基类默认说明)。")
class Rabbit(Animal):
def age(self):
print("兔子的年龄。")
class Horse(Animal):
def age(self):
print("马的年龄。")
a = Animal()
r = Rabbit()
h = Horse()
a.kind()
a.age()
r.kind()
r.age()
h.kind()
h.age()输出:
text
各种动物。
动物的年龄(基类默认说明)。
各种动物。
兔子的年龄。
各种动物。
马的年龄。Rabbit / Horse 未重写 kind,故沿用 Animal.kind;age 在子类中被重写,因此表现不同。
与「方法重载」的区别
Java 等语言里常见的编译期多态 / 方法重载(同名方法、不同参数列表)在 Python 中没有:后定义的同名函数会覆盖先定义的;动态派发主要依据运行时对象类型(以及可选的 functools.singledispatch 等模式),而不是仅靠参数个数区分重载。
运算符多态
+、* 等运算符对 int、str、list 等不同类型有不同含义;自定义类可通过 __add__ 等参与同一机制,见 运算符重载。
小结
- 多态:同一接口,不同实现;Python 中鸭子类型很普遍。
- 继承 + 重写是典型子类型多态;运算符重载是另一种「同一符号,不同语义」。
- Python 不以参数列表做方法重载;需要时分派可用
singledispatch等方案。