你要求的是所谓的多重调度。参见Julia语言示例,其中演示了不同类型的分派。
然而,在讨论这个问题之前,我们首先要解决为什么在Python中重载并不是你真正想要的。
为什么不超载?
首先,我们需要理解重载的概念,以及为什么它不适用于Python。
在使用可以区分数据类型的语言时
编译时,可以在
编译时。为…创造这样的替代功能的行为
编译时选择通常称为重载
函数。(维基百科)
Python是一种动态类型语言,因此重载的概念并不适用于它。然而,并不是所有的都失去了,因为我们可以在运行时创建这样的替代函数:
在编程语言中,将数据类型识别推迟到
运行时在备选项中进行选择
函数必须在运行时根据动态确定的值发生
函数参数的类型。其替代函数
以这种方式选择的实现引用最多
通常称为多方法。(维基百科)
因此,我们应该能够在python中使用多方法——或者,也可以称为:多分派。
多分派
多方法也被称为多重调度:
多调度或多方法是一些的特点
面向对象的程序设计语言,其中包含函数或方法
的运行时(动态)类型可以动态分派
不止一个论点。(维基百科)
Python不支持开箱即用1,但是,恰好有一个名为multipledispatch的优秀Python包可以做到这一点。
解决方案
下面是我们如何使用multipledispatch2包来实现你的方法:
>>> from multipledispatch import dispatch
>>> from collections import namedtuple
>>> from types import * # we can test for lambda type, e.g.:
>>> type(lambda a: 1) == LambdaType
True
>>> Sprite = namedtuple('Sprite', ['name'])
>>> Point = namedtuple('Point', ['x', 'y'])
>>> Curve = namedtuple('Curve', ['x', 'y', 'z'])
>>> Vector = namedtuple('Vector', ['x','y','z'])
>>> @dispatch(Sprite, Point, Vector, int)
... def add_bullet(sprite, start, direction, speed):
... print("Called Version 1")
...
>>> @dispatch(Sprite, Point, Point, int, float)
... def add_bullet(sprite, start, headto, speed, acceleration):
... print("Called version 2")
...
>>> @dispatch(Sprite, LambdaType)
... def add_bullet(sprite, script):
... print("Called version 3")
...
>>> @dispatch(Sprite, Curve, int)
... def add_bullet(sprite, curve, speed):
... print("Called version 4")
...
>>> sprite = Sprite('Turtle')
>>> start = Point(1,2)
>>> direction = Vector(1,1,1)
>>> speed = 100 #km/h
>>> acceleration = 5.0 #m/s**2
>>> script = lambda sprite: sprite.x * 2
>>> curve = Curve(3, 1, 4)
>>> headto = Point(100, 100) # somewhere far away
>>> add_bullet(sprite, start, direction, speed)
Called Version 1
>>> add_bullet(sprite, start, headto, speed, acceleration)
Called version 2
>>> add_bullet(sprite, script)
Called version 3
>>> add_bullet(sprite, curve, speed)
Called version 4
1. Python 3目前支持单分派
2. 注意不要在多线程环境中使用multipledispatch,否则会出现奇怪的行为。