2012-06-29 25 views
1

我試圖做一個函數,當在不同的參數類型上調用時做不同的事情。具體而言,該功能一應具備簽名如何在Python中重載?

def myFunc(string, string): 

和其他應具備的簽名

def myFunc(list): 

我怎麼能做到這一點,因爲我不能指定參數是否字符串或列表?

+2

簡而言之:Python語言中基本上沒有函數參數重載。這不是一個缺失的功能 - 這是一個語言概念。 – dajood

+0

IMO這就是爲什麼一個模式匹配庫(如球拍匹配)對Python很好 – Wes

+0

由於下面的答案應該建議,你必須開始考慮你的問題有點不同 - python有動態類型,這將使其解決問題的風格不同。在運行時可以進行一些類型檢查,但是如果沒有像Java這樣的靜態類型語言的動態分派,這將是一場艱苦的戰鬥。 – Ben

回答

1

*args可能是更好的辦法,但你可以這樣做:

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

但是,這可能是做這件事的可怕方式。

+3

不檢查None的相等性,尋找身份:'如果arg2不是None'。 –

+0

好點,編輯 – TankorSmash

+0

平等檢查'None'有什麼問題? –

0

把它定義爲以可變參數:

def myFunc(*args): 

然後你就可以通過lenisinstance,並將呼叫路由到適當的特定情況下,功能檢查的數量和參數類型。

但是,如果使用可選的命名參數,它可能會使代碼更清晰。如果你根本沒有使用超載,那會更好,但這不是python的方式。

2

即使通過參數計數,Python也不支持重載。你需要做的:

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

這是非常愚蠢的,或者只是重新考慮你的設計,不必過載。

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 
0

不能 - 例如一個類的實例方法可在運行時插入。

如果你有多個__init__爲實例類,你會與多個@classmethod的如from_stringsfrom_sequence

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