首页 > 解决方案 > [lambda x:i*x for i in range(4)] 的输出

问题描述

我遇到了这样一个面试问题:

告诉以下代码段的输出:

def num():
    return [lambda x:i*x for i in range(4)]
print([m(2)for m in num()])

我认为这很简单并且猜到了[0, 2, 4, 6]

很遗憾

In [1]: def num():
   ...:     return [lambda x:i*x for i in range(4)]

In [2]: print([m(2) for m in num()])
[6, 6, 6, 6]

查看其详细信息

In [5]: for _ in num():
   ...:     print(_)
   ...: 
<function num.<locals>.<listcomp>.<lambda> at 0x7f042411dc80>
<function num.<locals>.<listcomp>.<lambda> at 0x7f0424182378>
<function num.<locals>.<listcomp>.<lambda> at 0x7f04240dfc80>
<function num.<locals>.<listcomp>.<lambda> at 0x7f042410ed08>

定义一个 num 的这种晦涩语法的名称是什么,
它怎么会输出这样的结果[6, 6, 6,6]

我阅读了python - 列表推导中的 Lambdas - 代码日志

>>> y = 3
>>> f = lambda: y
>>> f()
3
>>> y = 4
>>> f()
4

把它放在一个标准的方式

In [15]: def foo(): return x

In [16]: x = 1; foo()
Out[16]: 1

In [17]: x = 4; foo()
Out[17]: 4

没有说明封闭的解释是不可想象的。

维基百科的答案最好将其视为对影子变量的闭包的晦涩用法

这也可以通过变量遮蔽(减少非局部变量的范围)来实现,尽管这在实践中不太常见,因为它不太有用并且不鼓励遮蔽。在这个例子中 f 可以被看作是一个闭包,因为 f 的主体中的 x 绑定到全局命名空间中的 x,而不是 g 的局部 x:

闭包(计算机编程) - 维基百科

x = 0

def f(y):
    return x + y

def g(z):
    x = 1  # local x shadows global x
    return f(z)

g(1)  # evaluates to 1, not 2

标签: pythonpython-3.xlambda

解决方案


lambda返回i调用时的值。lambda循环结束后调用3 ,i调用时也是如此。


推荐阅读