2

我正在尝试执行以下操作,这是我最终目标的代表性示例:

 yu = lambda x: 0
 for i in range(0,5):
      yu = lambda x: i + yu(x)

不幸的是,它返回:

RuntimeError: maximum recursion depth exceeded

当我做:

print yu(0)

打印语句应返回 10。

这样做的正确方法是什么?

4

5 回答 5

5

最后,你有:

yu = lambda x: i + yu(x)

但将在运行时yu查找,而不是在您构造 lambda 时查找。改为这样做:

for i in range(0,5):
    yu = lambda x, yu=yu: i + yu(x)

但是,这不会返回10。它20改为返回:

>>> yu = lambda x: 0
>>> for i in range(0,5):
...     yu = lambda x, yu=yu: i + yu(x)
... 
>>> yu(0)
20

因为 nowi仍然从上下文中查找(现在循环已经完成,所以它是4)。解决方案?也移动i到关键字参数:

for i in range(0,5):
    yu = lambda x, yu=yu, i=i: i + yu(x)

现在这有效:

>>> yu = lambda x: 0
>>> for i in range(0,5):
...     yu = lambda x, yu=yu, i=i: i + yu(x)
... 
>>> yu(0)
10

故事的道德启示?将您的上下文正确绑定到 lambda 的范围。

于 2013-02-27T23:08:56.900 回答
2
 yu = lambda x: i + yu(x)

这使得它yu成为一个始终调用自身的函数,保证了没有基本情况的无限递归。

为什么?好吧,您已经构建了一个闭包,其中yu(and ) 是循环i所属的函数或模块中的局部变量。for那不是你想要的;您想关闭 and 的当前值yui不是外部变量。

我不确定你为什么一开始就使用lambda它。如果要定义函数并为其命名,请使用def.

这是一个简单的解决方案:

def yu(x): return 0
def make_new_yu(yu, i):
    def new_yu(x): return i + yu(x)
    return new_yu
for i in range(0, 5):
    yu = make_new_yu(yu, i)

通过使包装明确,正确的方法成为最明显的方法。

当然,您可以使用lambdainsidemake_new_yu而不会使事情变得更加混乱:

def make_new_yu(yu, i):
    return lambda x: i + yu(x)

如果需要,您甚至可以将初始定义设为 a lambda。但是,如果您坚持不使用任何 def语句,则需要以某种方式强制将正确的值放入闭包中,例如,通过使用默认值技巧。这更容易出错——一旦你完成了它就更难阅读了。

如果您想直观地了解差异,而无需了解细节:函数体定义了一个新范围。因此,在该函数内定义函数(通过lambdadef)意味着您的闭包来自该新范围。

于 2013-02-27T23:10:53.687 回答
0

考虑到您尝试总结 0、1、2、3、4 的答案。如果这是正确的,您可以使用以下 lambda 表达式:

yu = lambda x: x + yu(x+1) if x<4 else x

因为yu(0)它提供了 10 个结果。中断条件是x需要保持小于 4 才能相加的值。

假设这是您想要做的,您应该省略循环以获得相当简洁的语句。

此 lambda 表达式与其他 lambda 表达式的不同之处在于根据给定参数产生不同的值(当不选择 0 作为参数 x 时,除 10 外)。

于 2013-02-27T23:52:31.110 回答
0

我相信我没有完全理解您的问题,但是有人可以检查他是否是这个意思吗?

我假设您不需要迭代器来生成数字列表

yu = lambda x: x[0] + yu(x[1:]) if x!=[] else 0
于 2019-03-31T15:14:17.663 回答
0
facto = lambda f: f if f == 0 else f + facto(f-1)
print(facto(4))
于 2020-06-28T12:48:33.687 回答