2 回答
TA贡献1719条经验 获得超6个赞
注意,函数应该是函数,而不是字符串,这样实现才能工作
如果您想返回使用一组 调用的函数kwargs,那么您已经非常接近了。我会使用位置参数 for func,然后你可以传入kwargs,func这更明确一点:
def myfunc(func, **kwargs):
return func(**kwargs)
然后,您可以将每对包装func, **kwargs为元组,并执行一个 for 循环:
# This would be called like
somelist = [(np.random.normal, { 'loc' : 0 , 'scale' : 1 , 'size' : 7 }),
(np.random.uniform , { 'low' : 0 , 'high' : 1 , 'size' : 7 })]
results = []
# append results to a list
for func, kwargs in somelist:
results.append(myfunc(func, **kwargs))
通过这种方式,您不必担心如何命名任何变量,并且更具可读性。您知道循环将处理成对的项目,在这种情况下是func, kwarg成对的,您的函数可以显式处理这些
处理字符串调用
所以有一些方法可以完成这个任务,它们有点棘手,但总体上不应该是可怕的。您需要修改myfunc以处理函数名称:
# func is now a string, unlike above
def myfunc(func, **kwargs):
# function will look like module.class.function
# so split on '.' to get each component. The first will
# be the parent module in global scope, and everything else
# is collected into a list
mod, *f = func.split('.') # f is a list of sub-modules like ['random', 'uniform']
# func for now will just be the module np
func = globals().get(mod)
for cls in f:
# get each subsequent level down, which will overwrite func to
# first be np.random, then np.random.uniform
func = getattr(func, cls)
return func(**kwargs)
我使用的原因globals().get(mod)是 a) 我假设您可能并不总是使用相同的模块,并且 b) 调用重命名的 import fromsys.modules将产生 a KeyError,这不是您想要的:
import sys
import numpy as np
sys.modules['np'] # KeyError
sys.modules['numpy']
# <module 'numpy.random' from '/Users/mm92400/anaconda3/envs/new36/lib/python3.6/site-packages/numpy/random/__init__.py'>
# globals avoids the naming conflict
globals()['np']
# <module 'numpy.random' from '/Users/mm92400/anaconda3/envs/new36/lib/python3.6/site-packages/numpy/random/__init__.py'>
然后getattr(obj, attr)将返回每个后续模块:
import numpy as np
getattr(np, 'random')
# <module 'numpy.random' from '/Users/mm92400/anaconda3/envs/new36/lib/python3.6/site-packages/numpy/random/__init__.py'>
# the dotted access won't work directly
getattr(np, 'random.uniform')
# AttributeError
所以,总共:
import numpy as np
func, kwargs = ('np.random.normal', { 'loc' : 0 , 'scale' : 1 , 'size' : 7 })
myfunc(func, **kwargs)
array([ 0.83276777, 2.4836389 , -1.07492873, -1.20056678, -0.36409906,
-0.76543554, 0.90191746])
您可以将其扩展到第一部分中的代码
TA贡献1946条经验 获得超4个赞
您可以设计一个将其他函数作为输入并执行它们的函数。这就是**运营商所做的:
def myfun(**kwargs):
kwargs['fun_1'](**kwargs['arg_1']) # calls the function kwargs[fun_1] with the keyword args given in kwargs[arg_1]
kwargs['fun_2'](**kwargs['arg_2'])
然后,您将像这样指定您的 kwargs:
myfun(fun_1=np.random.normal,
arg_1={'loc': 0, 'scale': 1, 'size': 7},
fun_2=np.random.uniform,
arg_2={'low': 0, 'high': 1, 'size': 7},
)
请注意如何np.random.normal不在引号中 - 我们通过引用引用实际函数,但尚未调用它(因为我们想在 中执行此操作myfun(),而不是现在)。
我认为这个操作符(*列表和**字典)没有正式名称,但我称它为解包操作符,因为它将数据结构解包到函数参数中。
在这种情况下,声明显式命名参数通常更安全- 您需要提出一种模式,以便使用您的函数的人知道他们应该如何命名他们的关键字。
添加回答
举报