Python 中的重载函数
- 2025-03-13 09:15:00
- admin 原创
- 12
问题描述:
Python 中可以有重载函数吗?
在 C# 中我会做类似的事情
void myfunction (int first, string second)
{
# Some code
}
void myfunction (int first, string second, float third)
{
# Some different code
}
然后当我调用该函数时,它会根据参数的数量区分两者。在 Python 中可以做类似的事情吗?
解决方案 1:
编辑有关 Python 3.4 中的新单调度通用函数,请参阅http://www.python.org/dev/peps/pep-0443/
通常不需要在 Python 中重载函数。Python 是动态类型的,并且支持函数的可选参数。
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
解决方案 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)
函数来检查参数的数量并根据需要委托。这种“黑客”通常是通过装饰器完成的。在这种情况下,你可以实现类似以下效果:
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 - 单分派泛型函数
解决方案 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)
请注意,函数返回的 lambda根据未命名参数overload
的数量来选择要调用的函数。
该解决方案并不完美,但目前我无法写出更好的方案。
解决方案 4:
直接这样做是不可能的。不过,你可以对给定的参数使用显式类型检查,尽管这通常是不被接受的。
Python 是动态的。如果你不确定一个对象能做什么,只需try:
调用它的方法,然后就会except:
出错。
如果您不需要根据类型进行重载,而只需根据参数的数量进行重载,请使用关键字参数。
解决方案 5:
以下是使用默认参数和关键字参数重载 Python 函数的方法
from multipledispatch import dispatch
# FOR hi(a: int, b: int = 3)
@dispatch(int, int)
def _hi(a: int, b: int):
print(a, b)
@dispatch(int, int)
def hi(a: int, b: int = 3):
_hi(a, b)
@dispatch(int, b=int)
def hi(a: int, *, b: int = 3):
_hi(a, b)
# FOR hi(a: str, b: int = 3)
@dispatch(str, int)
def _hi(a: str, b: int):
print(a, b, 'str!')
@dispatch(str, int)
def hi(a: str, b: int = 3):
_hi(a, b)
@dispatch(str, b=int)
def hi(a: str, *, b: int = 3):
_hi(a, b)
hi(2)
hi(2, 3)
hi(2, b=3)
hi('2')
hi('2', 3)
hi('2', b=3)
输出
2 3
2 3
2 3
2 3 str!
2 3 str!
2 3 str!
解决方案 6:
在 Python 中,重载方法比较棘手。但是,可以使用传递字典、列表或原始变量。
我已经针对我的用例尝试了一些方法,这可以帮助人们理解重载方法。
让我们以 Stack Overflow 上的一个问题为例:
类重载方法可以调用不同类的方法。
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']}
因此,可以通过方法重载来实现列表、字典或原始变量的处理。
用你的代码尝试一下。