You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何从函数列表构造依次调用所有函数的新Python函数?

解决Python中用partial构造依次调用函数列表的新函数问题

首先来分析你遇到的RecursionError原因:
你写的循环里,每次赋值f = lambda x: g(f(x)),这里的gf是闭包引用的变量,Python的闭包是延迟绑定的——也就是说,直到你调用f的时候,才会去取gf的当前值。循环结束后,g最终指向列表里最后一个函数add4,而f也变成了最后一次循环生成的lambda。这时候调用f(0),实际执行的是add4(f(0)),而f(0)又会再次调用这个lambda,于是就陷入了无限递归,触发递归深度超限错误。

接下来是用partial实现的方案,核心是要在每次循环时捕获当前的gf的具体值,避开闭包延迟绑定的坑:

首先导入partial

from functools import partial

方案一:直接用partial结合lambda绑定当前值

add2 = lambda x: x+2
add3 = lambda x: x+3
add4 = lambda x: x+4
funcs = [add2, add3, add4]

f = funcs[0]
for g in funcs[1:]:
    # 用partial把当前循环的f和g固定下来,避免闭包延迟绑定
    f = partial(lambda current_f, current_g, x: current_g(current_f(x)), f, g)

# 测试调用
print(f(0))  # 输出 9(0+2+3+4的结果)

方案二:用辅助函数配合partial更清晰

from functools import partial

add2 = lambda x: x+2
add3 = lambda x: x+3
add4 = lambda x: x+4
funcs = [add2, add3, add4]

# 定义一个辅助函数,实现先调用f再调用g的逻辑
def apply_two(f, g, x):
    return g(f(x))

f = funcs[0]
for g in funcs[1:]:
    f = partial(apply_two, f, g)

print(f(0))  # 同样输出9

这个方案有效的原因是:partial会把当前循环中的fg即时引用值绑定到新的可调用对象里,而不是像之前的lambda那样等到调用时才去查找变量。这样每次循环生成的f都是基于当时的函数组合,不会被后续循环的变量覆盖。

另外,如果不想用partial,还可以通过给lambda设置默认参数的方式捕获当前值(思路和partial一致):

f = funcs[0]
for g in funcs[1:]:
    f = lambda x, current_f=f, current_g=g: current_g(current_f(x))

print(f(0))  # 输出9

内容的提问来源于stack exchange,提问作者hr0m

火山引擎 最新活动