让我们考虑一下以下代码:

def f(x):
    return x

sol = [f]
sol.append(lambda x: sol[0](x) + x)
sol.append(lambda x: sol[1](x) + x)

print(sol[0](1), sol[1](1), sol[2](1))
# 1 2 3

这样做,我得到了我想要的东西.现在,让我们做完全相同的事情,但有for loop:

def f(x):
    return x

sol = [f]
for i in range(1, 3):
    sol.append(lambda x: sol[i](x) + x)

print(sol[0](1), sol[1](1), sol[2](1))
# RecursionError: maximum recursion depth exceeded.

有人能给我解释一下发生了什么事吗?

乍一看,我认为这个问题与one类似:Lambda函数反复调用自己,直到它在递归限制处触底.但我看不出为什么会是这样.

推荐答案

您的代码创建了一个闭包,以便在调用lambdas时,它们不使用创建时有效的值i,而是使用值current i,即2.因此,它等同于:

sol = [f]
sol.append(lambda x: sol[2](x) + x)
sol.append(lambda x: sol[2](x) + x)

要解决这个问题,您需要在创建lambda时捕获循环索引值.这可以通过lambda绑定循环值来实现(参见下面的解决方案).

原始代码的另一个问题是循环索引从1运行到2,而实际上它需要从0到1(以便lambdas引用列表中的前面的函数,而不是它们自己).

这两个问题都可以按如下方式修复:

sol = [f]
for i in range(0, 2):
    sol.append((lambda i: lambda x: sol[i](x) + x)(i))

这会产生所需的行为.还有一个小窍门,你可以用来让它更简洁:

sol = [f]
for i in range(0, 2):
    sol.append(lambda x, i=i: sol[i](x) + x)

这将i绑定为可选第二个参数的缺省值.行为上的唯一区别是第二个参数现在可以由调用方指定,您可能想要也可能不想要.

Python相关问答推荐

在Python中管理多个OpenGVBO和VAO实例

Matplotlib轮廓线值似乎不对劲

指示组内的rejected_time是否在creation_timestamp后5分钟内

如何在Python中使用时区夏令时获取任何给定本地时间的纪元值?

比较两个数据帧并并排附加结果(获取性能警告)

如何将双框框列中的成对变成两个新列

无法定位元素错误404

为什么以这种方式调用pd.ExcelWriter会创建无效的文件格式或扩展名?

try 将一行连接到Tensorflow中的矩阵

形状弃用警告与组合多边形和多边形如何解决

为一个组的每个子组绘制,

SQLAlchemy bindparam在mssql上失败(但在mysql上工作)

如何在Pyplot表中舍入值

如何排除prefecture_related中查询集为空的实例?

在代码执行后关闭ChromeDriver窗口

如何获取Python synsets列表的第一个内容?

交替字符串位置的正则表达式

基于多个数组的多个条件将值添加到numpy数组

查看pandas字符列是否在字符串列中

计算机找不到已安装的库'