2016-08-02 55 views
2

在python中是否有等效於R的do.call相當於Python中的「do.call」

do.call(what = 'sum', args = list(1:10)) #[1] 55 
do.call(what = 'mean', args = list(1:10)) #[1] 5.5 

?do.call 
# Description 
# do.call constructs and executes a function call from a name or a function and a list of arguments to be passed to it. 

回答

2

這沒有內置的,但它很容易構建一個等效。

你可以看一下從使用__builtin__(Python的2)或builtins(Python 3中)模塊則適用任意參數與*args**kwargs語法的內置插件命名空間中的物體:

try: 
    # Python 2 
    import __builtin__ as builtins 
except ImportError: 
    # Python 3 
    import builtins 

def do_call(what, *args, **kwargs): 
    return getattr(builtins, what)(*args, **kwargs) 

do_call('sum', range(1, 11)) 

一般說起來,我們不用Python來做這件事。如果必須字符串翻譯成函數對象,它通常最好是建立一個自定義詞典:

functions['sum'](range(1, 11)) 

這可讓您嚴格控制是什麼名稱:

functions = { 
    'sum': sum, 
    'mean': lambda v: sum(v)/len(v), 
} 

然後從字典,而不是查找功能可用於動態代碼,通過調用內置的破壞性或破壞性效果來防止用戶對自己產生干擾。

+1

接下來的問題是:這是個好主意嗎? - 不,不,不。 –

+0

@KonradRudolph:nope;有更好的參數化功能。 –

3

do.call幾乎是splat operator的Python中的等價物:

def mysum(a, b, c): 
    return sum([a, b, c]) 

# normal call: 
mysum(1, 2, 3) 

# with a list of arguments: 
mysum(*[1, 2, 3]) 

請注意,我已經確定自己sum功能,因爲Python的sum已經預計一list作爲參數,所以你的原代碼將只是

sum(range(1, 11)) 

R具有另一特點:do.call在內部執行其第一個參數的函數的查找。這意味着即使它是一個字符串而不是實際的函數,它也可以找到該函數。上面的Python等價物沒有這樣做 - 參見Martijn的解答。關於這個,雖然兩件事情:

  1. 這不是特定於R. do.call事實上,功能查找可能是由內部進行match.fun
  2. 這是一個「太神奇」的例子,我強烈建議不要在R中編寫這樣的代碼,更不用說更強類型的語言了:它顛覆了類型系統,並且通常導致錯誤。例如,do.call的R文檔對於what是字符串時執行的操作非常模糊。例如,考慮到其描述,期望do.call('base::sum', list(1, 2))應該可以工作是合理的。唉,事實並非如此。
+0

感謝@KonradRudolph的幫助。原則上,我正在解析一個文本文件,其中指定了聚合函數。我想避免使用將字符串映射到其函數的開關/字典。任何想法呢? – Deena

+0

@Dee使用字典(實際上,no:使用提供類似字典的界面的''context'對象,但將被調用函數的副作用與程序的其餘部分隔離開來。無論是在Python還是在R中,這都是適合這種情況的解決方案。讓用戶執行任意函數永遠不是一個好主意。 –