Python 通过单分派泛函数部分支持了方法重载。
官方文档是这样定义泛函数以及单分派函数的:
A generic function is composed of multiple functions implementing the same operation for different types. Which implementation should be used during a call is determined by the dispatch algorithm. When the implementation is chosen based on the type of a single argument, this is known as single dispatch.
也就是说单分派泛函数(single dispatch)可以根据第一个参数的类型,来判断执行哪一个函数体。
那么我们使用 singledispatch 重写上面的例子:
首先我们要从functools 中导入 singledispatch
from functools import singledispatch
singledispatch 是作为装饰器使用的函数。装饰器是 Python 中的语法糖,@singledispatch 实际上相当于 singledispatch(fprint),这里我们并不关心 singledispatch 的内部实现,我们只需知道 singledispatch 可以实现分派机制就行。NotImplemented 是 Python 中的内置常量,提醒我们没有实现某个功能。注意这与 NotImplementedError 有天壤之别,后者会导致异常出现,终止程序。当调用 fprint() 函数时,如果参数的类型没有被注册,那么默认会执行使用 @singledispatch 装饰的函数。
@singledispatch
def fprint(obj):
return NotImplemented
我们使用 @<主函数名>.register(type) 来装饰专门函数。要注意分派函数可以有任意多个参数,但是调用函数时执行哪一部分功能只由函数第一个参数决定,也就是由 register 中声明的参数类型决定。 而对于专门函数来说,函数名是无关紧要的,使用 _ 更加简洁明了。
from functools import singledispatch
@singledispatch
def fprint(obj):
return NotImplemented
@fprint.register(str)
def _(obj):
print('我是一个字符串')
print(obj)
@fprint.register(int)
def _(obj):
print('我是一个整型')
print(obj)
if __name__ == '__main__':
fprint('asdasdas')
fprint(5)
Python 3.7 中新增了一个功能:即使用 type annotions 来注明第一个参数的类型。打印结果,与使用装饰器参数得到的结果相同。
from functools import singledispatch
@singledispatch
def fprint(obj):
return NotImplemented
@fprint.register
def _(obj:str):
print('我是一个字符串')
print(obj)
@fprint.register
def _(obj:int):
print('我是一个整型')
print(obj)
@fprint.register
def _(obj:list):
print('我是一个列表')
print(obj)
if __name__ == '__main__':
fprint('asdasdas')
fprint(5)
fprint([1,2,3])