2016-08-02 157 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中,这都是适合这种情况的解决方案。让用户执行任意函数永远不是一个好主意。 –