在python中“重载”函数的最佳方法?

时间:2015-06-07 11:50:14

标签: python overloading

我正在尝试在python中执行类似的操作:

def foo(x, y):
    # do something at position (x, y)

def foo(pos):
    foo(pos.x, pos.y)

所以我想根据我提供的参数数量调用不同版本的foo。这当然不起作用,因为我重新定义了foo

实现这一目标的最优雅方式是什么?我宁愿不使用命名参数。

5 个答案:

答案 0 :(得分:5)

通常您要么定义两个不同的功能,要么执行以下操作:

def foo(x, y = None):
    if y is None:
        x, y = x.x, x.y
    # do something at position (x, y)

如果你已经习惯了有重载的语言,那么定义两个不同函数的选项看起来很笨拙,但是如果你已经习惯了像Python或C这样的语言,那么它就是你所做的。 Python中上面代码的主要问题是记录第一个参数有点尴尬,在两种情况下并不一样。

另一种选择是定义带有pos的foo版本,但也为用户提供类型:

Pos = collections.namedtuple('Pos', 'x y')

然后任何想写foo(x,y)的人都可以写foo(Pos(x,y))。当然,由于必须创建一个对象,因此性能成本很低。

答案 1 :(得分:5)

您可以使用默认参数,但如果您想在python中使用重载,最好的方法是:

from pytyp.spec.dispatch import overload

@overload
def foo(x,y):

@foo.overload
def foo(x, y,z):

Pytyp是一个python包(你可以从https://pypi.python.org/pypi/pytyp下载)。它包括模块pytyp.spec.dispatch,它包含装饰器,如重载。如果它被放在方法上,那么将为所有重载方法调用此方法..

答案 2 :(得分:2)

您尝试实现的设计看似糟糕,可能会考虑使用不同的功能名称:

def do_something_by_coordinates(x, y):
    pass

def do_something_by_position(pos):
    do_something_by_coordinates(pos.x, pos.y)

如果您确实需要,可以使用kwargs
Understanding kwargs in Python

答案 3 :(得分:2)

你可以做很多事情,比如命名默认参数。

然而,它看起来像你想要的是“多次发送”,并且有一些装饰器的实现可以帮助你做那种事情。这是one implementation看起来像:

>>> from multipledispatch import dispatch

>>> @dispatch(int, int)
... def add(x, y):
...     return x + y

>>> @dispatch(Position)
... def add(pos):
...     return "%s + %s" % (pos.x, pos.y)

>>> add(1, 2)
3

>>> pos = Position(3, 4)
>>> add(pos)
7

虽然@ functools.singledispatch即将来到Python 3.4但我认为这不适用于您的示例,因为在一个案例中您有多个参数。

答案 4 :(得分:0)

设置默认值的一种方法:

def foo(x, y=None):    
    # now for example, you can call foo(1) and foo(1,2)     

foo内,你可以检查y == None是否有两种情况的逻辑。

请注意,如果您将功能分开,则可以拥有更好的设计,不要尝试使用同时接受坐标和位置的功能。