我怎样才能在Python中重载?

时间:2012-06-29 21:44:52

标签: python

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

def myFunc(string, string):

另一个应该有签名

def myFunc(list):

我怎么能这样做,因为我不允许指定参数是字符串还是列表?

6 个答案:

答案 0 :(得分:2)

Python不支持重载,即使是参数计数也是如此。你需要这样做:

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

这非常愚蠢,或者只是重新考虑你的设计而不必过载。

答案 1 :(得分: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

答案 2 :(得分:1)

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

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

但这可能是一种可怕的做法。

答案 3 :(得分: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

答案 4 :(得分:0)

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

def myFunc(*args):

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

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

答案 5 :(得分:0)

您不能 - 例如,可以在运行时插入类实例方法。

例如,如果某个类有多个__init__,那么您最好使用多个@classmethod,例如from_stringsfrom_sequence