目前我正在使用一个包含函数名称的字符串列表来修复我的软件流程:
flow = [
"func1",
"func2",
"func3",
"func4",
"func5"
]
然后我遍历流程并调用每个传递选项:
options = {}
[getattr(__import__(phase), phase)(options) for phase in flow]
我想知道是否有可能做同样的事情,但避免副作用,使用减少。目前,这种方法使得函数接收选项,但是没有必要返回下一个函数的选项,所以我正在改变在其他范围内声明的选项。
感谢。
答案 0 :(得分:1)
您可以使用functools.reduce
(在Haskell等其他函数式编程语言中有时称为fold
)来确实调用该函数。
在这种情况下,您需要定义一个函数取两个参数:旧累加器值和元素本身。您只需忽略旧值并在元素上调用该函数。
因此,对于通用函数f(x)
,您可以使用以下函数执行此操作:
functools.reduce(lambda _,x:f(x),list,initializer=0)
所以在你的情况下会是:
options = {}
functools.reduce(lambda _,phase:getattr(__import__(phase),phase)(options),flow,initializer=0)
修改强>:
在重新阅读你的问题之后,在我看来,每个函数都作为输入options
,并生成应该传递给下一个函数的“新”选项。那么第一个函数的返回是下一个函数的lambda
的第一个参数。所以你可以把它折叠起来像:
first_options = {}
functools.reduce(lambda options,phase:getattr(__import__(phase),phase)(options),flow,initializer=first_options)
这将导致相当于:
的东西options_0 = first_options
options_1 = getattr(__import__(phase),flow[0])(options_0)
options_2 = getattr(__import__(phase),flow[1])(options_1)
# ...
return options_n
但当然会发生 reduce
。
答案 1 :(得分:0)
所以reduce接受一个函数,比如reduce_func
,它接受2个参数。当它通过一个列表时,前两个项目作为第一个调用的reduce_func
的参数,然后在每个后续调用中,使用返回值作为第一个参数,列表中的下一个值作为第二个参数。这意味着,对于您,reduce_func
需要是以下
def reduce_func(param, f):
return f(param)
,您的列表必须如下:
[options, func1, func2, func3, func4]
现在,我使用了一系列函数,但没有使用import。代替f
,您可以将[module].[function]
作为字符串传递(称为func_str
之类的参数),并在reduce_func
内部进行一些拆分