<p>您所要求的是称为<em>多重调度</em>。请参阅演示不同类型分派的<a href="http://nbviewer.ipython.org/gist/StefanKarpinski/b8fe9dbb36c1427b9f22" rel="noreferrer">Julia</a>语言示例。</p>
<p>然而,在讨论这个问题之前,我们将首先讨论为什么在python中<em>重载</em>并不是您真正想要的。</p>
<h2>为什么不超载呢?</h2>
<p>首先,需要理解重载的概念以及为什么它不适用于python。</p>
<blockquote>
<p>When working with languages that can discriminate data types at
compile-time, selecting among the alternatives can occur at
compile-time. The act of creating such alternative functions for
compile-time selection is usually referred to as overloading a
function. (<a href="http://en.wikipedia.org/wiki/Multiple_dispatch" rel="noreferrer">Wikipedia</a>)</p>
</blockquote>
<p>Python是一种<a href="https://pythonconquerstheuniverse.wordpress.com/2009/10/03/static-vs-dynamic-typing-of-programming-languages/" rel="noreferrer">dynamically</a>类型语言,因此重载的概念并不适用于它。但是,并不是所有的都丢失了,因为我们可以在运行时创建这样的<em>替代函数</em>:</p>
<blockquote>
<p>In programming languages that defer data type identification until
run-time the selection among alternative
functions must occur at run-time, based on the dynamically determined
types of function arguments. Functions whose alternative
implementations are selected in this manner are referred to most
generally as <em>multimethods</em>. (<a href="http://en.wikipedia.org/wiki/Multiple_dispatch" rel="noreferrer">Wikipedia</a>)</p>
</blockquote>
<p>因此,我们应该能够在python中执行<em>多方法</em>,或者,也就是我们所说的:<em>多分派</em>。</p>
<h2>多次调度</h2>
<p>多方法也称为多分派:</p>
<blockquote>
<p>Multiple dispatch or multimethods is the feature of some
object-oriented programming languages in which a function or method
can be dynamically dispatched based on the run time (dynamic) type of
more than one of its arguments. (<a href="http://en.wikipedia.org/wiki/Multiple_dispatch" rel="noreferrer">Wikipedia</a>)</p>
</blockquote>
<p>Python不支持这种现成的<sup>1</sup>,但是,碰巧有一个名为<a href="https://pypi.python.org/pypi/multipledispatch/" rel="noreferrer">multipledispatch</a>的优秀Python包可以做到这一点。</p>
<h2>解决方案</h2>
<p>下面是我们如何使用<a href="https://pypi.python.org/pypi/multipledispatch/" rel="noreferrer">multipledispatch</a><sup>2</sup>包来实现您的方法:</p>
<pre><code>>>> 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
>>> 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
</code></pre>
<p><sub>
一。Python 3目前支持<a href="https://docs.python.org/3/library/functools.html#functools.singledispatch" rel="noreferrer">single dispatch</a>
</sub><br/>
<sub>
2。注意不要在多线程环境中使用<a href="https://pypi.python.org/pypi/multipledispatch/" rel="noreferrer">multipledispatch</a>,否则会出现奇怪的行为。
</sub></p>