在python中是否有等价的R 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.
答案 0 :(得分:3)
没有内置功能,但构建等效内容非常容易。
您可以使用__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': sum,
'mean': lambda v: sum(v) / len(v),
}
然后从该字典中查找函数:
functions['sum'](range(1, 11))
这使您可以严格控制动态代码可用的名称,防止用户通过调用内置函数来破坏他们的破坏性或破坏性效果。
答案 1 :(得分:3)
do.call
几乎相当于Python中的splat operator:
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的解决方案。关于这一点的两件事:
do.call
。实际上,函数查找可能由match.fun
在内部执行。do.call
是一个字符串时,what
的R文档对于执行什么操作非常模糊。例如,鉴于其描述,期望do.call('base::sum', list(1, 2))
应该起作用是合理的。唉,它没有。答案 2 :(得分:0)
与先前的答案相似,但是为什么这么复杂?
def do_call(which, args=None, kwargs = None):
if args is None and kwargs is not None:
return which(**kwargs)
elif args is not None and kwargs is None:
return which(*args)
else:
return which(*args, **kwargs)
Python的sum
与R的sum
不同(1个预期参数列表与
任意预期R中有许多论点。因此,我们定义了自己的总和(mysum
)
其行为与R的sum
类似。我们以类似的方式定义mymean
。
def mysum(*args):
return sum(args)
def mymean(*args):
return sum(args)/len(args)
现在,我们可以在Python中重新创建您的示例-作为R函数调用的合理1:1转换。
do_call(what = mymean, args=[1, 2, 3])
## 2.0
do_call(what = mysum, args=[1, 2, 3])
## 6
对于带有参数名称的函数,我们对kwargs使用dict,其中参数 名称是字典的键(作为字符串),其值是值。
def myfunc(a, b, c):
return a + b + c
do_call(what = myfunc, kwargs={"a": 1, "b": 2, "c": 3})
## 6
# we can even mix named and unnamed parts
do_call(what = myfunc, args = [1, 2], kwargs={"c": 3})
## 6
答案 3 :(得分:0)
我们永远不会在打字方面见得面目全非。感谢您分享您的观点。我认为有可能通过辩论而不必说“你错了”
您是否尝试过,“您的*位置错误”,这对个人的敌意较少。或者,“您可能要考虑...。”
如果您可以更改方法,我很乐意进一步考虑您的观点。