我正在尝试制作一个在不同参数类型上调用时执行不同操作的函数。具体来说,其中一项功能应具有签名
def myFunc(string, string):
另一个应该有签名
def myFunc(list):
鉴于不允许我指定参数是字符串还是列表,我该怎么做?
我正在尝试制作一个在不同参数类型上调用时执行不同操作的函数。具体来说,其中一项功能应具有签名
def myFunc(string, string):
另一个应该有签名
def myFunc(list):
鉴于不允许我指定参数是字符串还是列表,我该怎么做?
Python 不支持重载,即使是按参数计数。你需要做:
def foo(string_or_list, string = None):
if isinstance(string_or_list, list):
...
else:
...
这很愚蠢,或者只是重新考虑您的设计以不必超载。
在http://code.activestate.com/recipes/577065-type-checking-function-overloading-decorator/有一个食谱可以满足您的需求;
基本上,你用@takes 和@returns 类型声明来包装你的函数的每个版本;当您调用该函数时,它会尝试每个版本,直到找到不会引发类型错误的版本。
编辑:这是一个精简版;这可能不是一件好事,但如果你必须这样做,方法如下:
from collections import defaultdict
def overloaded_function(overloads):
"""
Accepts a sequence of ((arg_types,), fn) pairs
Creates a dispatcher function
"""
dispatch_table = defaultdict(list)
for arg_types,fn in overloads:
dispatch_table[len(arg_types)].append([list(arg_types),fn])
def dispatch(*args):
for arg_types,fn in dispatch_table[len(args)]:
if all(isinstance(arg, arg_type) for arg,arg_type in zip(args,arg_types)):
return fn(*args)
raise TypeError("could not find an overloaded function to match this argument list")
return dispatch
这是它的工作原理:
def myfn_string_string(s1, s2):
print("Got the strings {} and {}".format(s1, s2))
def myfn_list(lst):
print("Got the list {}".format(lst))
myfn = overloaded_function([
((basestring, basestring), myfn_string_string),
((list,), myfn_list)
])
myfn("abcd", "efg") # prints "Got the strings abcd and efg"
myfn(["abc", "def"]) # prints "Got the list ['abc', 'def']"
myfn(123) # raises TypeError
不是一个完美的解决方案,但如果第二个字符串参数永远不会合法None
,您可以尝试:
def myFunc( firstArg, secondArg = None ):
if secondArg is None:
# only one arg provided, try treating firstArg as a list
else:
# two args provided, try treating them both as strings
*args
可能是更好的方法,但您可以执行以下操作:
def myFunc(arg1, arg2=None):
if arg2 is not None:
#do this
else:
#do that
但这可能是一种糟糕的做法。
将其定义为采用可变参数:
def myFunc(*args):
len
然后,您可以通过和检查参数的数量和类型,isinstance
并将调用路由到适当的特定于案例的函数。
但是,如果您使用可选的命名参数,它可能会使代码更清晰。如果你根本不使用重载会更好,这有点不是python的方式。
你不能——例如一个类实例方法可以在运行时插入。
例如,如果一个类有多个__init__
,那么最好使用多个@classmethod
,例如from_strings
orfrom_sequence