Python中的重载函数

Posted

技术标签:

【中文标题】Python中的重载函数【英文标题】:Overloaded functions in Python 【发布时间】:2011-10-30 02:14:31 【问题描述】:

Python 中是否可以重载函数?

在 C# 中我会做类似的事情

void myfunction (int first, string second)

    # Some code


void myfunction (int first, string second, float third)

    # Some different code

然后当我调用该函数时,它会根据参数的数量区分两者。是否可以在 Python 中做类似的事情?

【问题讨论】:

这似乎是一个重复的帖子。另外请不要标记为 C#,因为问题与 C# 无关。 function-overloading-in-python-missing Function overloading in Python: Missing的可能重复 Python function overloading的可能重复 相关(不重复):How can I detect duplicate method names in a Python class? 【参考方案1】:

编辑对于 Python 3.4 中新的单调度泛型函数,请参阅http://www.python.org/dev/peps/pep-0443/

您通常不需要在 Python 中重载函数。 Python 是dynamically typed,支持函数的可选参数。

def myfunction(first, second, third = None):
    if third is None:
        #just use first and second
    else:
        #use all three

myfunction(1, 2) # third will be None, so enter the 'if' clause
myfunction(3, 4, 5) # third isn't None, it's 5, so enter the 'else' clause

【讨论】:

但请注意,根据参数的类型调用不同的函数要困难得多(尽管并非不可能)。 嗯,重载/多态和条件是有区别的。你的意思是我们不需要多态性,因为我们有条件? @Val 我是说,基本上,在动态类型语言中,您不需要将重载作为语言功能,因为您可以在代码中轻松地模拟它,因此可以通过这种方式获得多态性。 @Val 我是说在可选参数和动态类型之间,就像你在 Python 中拥有它们的方式一样,你不需要 Java 风格的方法重载来实现多态性。 @navidoo 我认为这不是一个好主意——一个函数不应该返回完全不同类型的东西。但是,您始终可以在主函数内部定义一个本地生成器函数,调用它,然后返回生成的生成器——从外部看,它就像主函数是一个生成器一样。 Example here.【参考方案2】:

在普通的 Python 中,你不能做你想做的事。有两个接近的近似值:

def myfunction(first, second, *args):
    # 'args' is a tuple of extra arguments

def myfunction(first, second, third=None):
    # 'third' is optional

然而,如果你真的想要这样做,你当然可以让它工作(冒着冒犯传统主义者的风险;o)。简而言之,您将编写一个wrapper(*args) 函数,根据需要检查参数和委托的数量。这种“hack”通常是通过装饰器完成的。在这种情况下,您可以实现以下目标:

from typing import overload

@overload
def myfunction(first):
    ....

@myfunction.overload
def myfunction(first, second):
    ....

@myfunction.overload
def myfunction(first, second, third):
    ....

您可以通过使overload(first_fn) 函数(或构造函数)返回一个可调用对象来实现这一点,其中__call__(*args) 方法执行上述委托,并且overload(another_fn) 方法添加了可以委托给的额外功能。

您可以在http://acooke.org/pytyp/pytyp.spec.dispatch.html 看到类似的示例,但这是按类型重载方法。这是一种非常相似的方法...

类似的东西(使用参数类型)被添加到 Python 3 - PEP 443 -- Single-dispatch generic functions

【讨论】:

range 内置函数使用了重载,所以它真的是 hack 吗? github.com/python/typeshed/blob/master/stdlib/2and3/…【参考方案3】:

是的,这是可能的。我在 Python 3.2.1 中编写了以下代码:

def overload(*functions):
    return lambda *args, **kwargs: functions[len(args)](*args, **kwargs)

用法:

myfunction=overload(no_arg_func, one_arg_func, two_arg_func)

请注意,overload 函数返回的 lambda 会根据 未命名 参数的数量选择要调用的函数。

解决方案并不完美,但目前我写不出更好的东西。

【讨论】:

【参考方案4】:

这是不可能的。您可以对给定的参数使用显式类型检查,尽管这通常是不受欢迎的。

Python 是动态的。如果您不确定对象可以做什么,只需try: 并在其上调用方法,然后except: 错误。

如果您不需要根据类型重载,而只需要根据参数数量进行重载,请使用关键字参数。

【讨论】:

我认为他不知道可选参数。【参考方案5】:

在 Python 中重载方法很棘手。但是,可能会用到传递字典、列表或原始变量。

我已经为我的用例尝试了一些东西,这有助于理解人们重载方法。

让我们以堆栈溢出问题之一为例:

类重载方法,调用不同类的方法。

def add_bullet(sprite=None, start=None, headto=None, spead=None, acceleration=None):

从远程类传递参数:

add_bullet(sprite = 'test', start=Yes, headto='lat':10.6666, 'long':10.6666, accelaration=10.6

或者

add_bullet(sprite = 'test', start=Yes, headto='lat':10.6666, 'long':10.6666, speed=['10','20,'30']

因此,正在处理来自方法重载的列表、字典或原始变量。

试试你的代码。

【讨论】:

可能不是accelaration。更像accelerationae)。

以上是关于Python中的重载函数的主要内容,如果未能解决你的问题,请参考以下文章

python中函数重载和重写

Python中的函数重载:缺少[关闭]

Python中的函数重载:缺少[关闭]

python 类中的运算符和函数重载

Python 没有函数重载?如何用装饰器实现函数重载?

python中有函数重载吗