1

我正在尝试制作一个在不同参数类型上调用时执行不同操作的函数。具体来说,其中一项功能应具有签名

def myFunc(string, string):

另一个应该有签名

def myFunc(list):

鉴于不允许我指定参数是字符串还是列表,我该怎么做?

4

6 回答 6

2

Python 不支持重载,即使是按参数计数。你需要做:

def foo(string_or_list, string = None):
    if isinstance(string_or_list, list):
        ...
    else:
        ...

这很愚蠢,或者只是重新考虑您的设计以不必超载。

于 2012-06-29T21:47:30.150 回答
2

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
于 2012-06-29T21:50:14.933 回答
1

不是一个完美的解决方案,但如果第二个字符串参数永远不会合法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
于 2012-06-29T22:53:30.233 回答
1

*args可能是更好的方法,但您可以执行以下操作:

def myFunc(arg1, arg2=None):
  if arg2 is not None: 
     #do this
  else:
     #do that

但这可能是一种糟糕的做法。

于 2012-06-29T21:48:46.127 回答
0

将其定义为采用可变参数:

def myFunc(*args):

len然后,您可以通过和检查参数的数量和类型,isinstance并将调用路由到适当的特定于案例的函数。

但是,如果您使用可选的命名参数,它可能会使代码更清晰。如果你根本不使用重载会更好,这有点不是python的方式。

于 2012-06-29T21:46:26.503 回答
0

你不能——例如一个类实例方法可以在运行时插入。

例如,如果一个类有多个__init__,那么最好使用多个@classmethod,例如from_stringsorfrom_sequence

于 2012-06-29T21:51:07.417 回答