在 Python 中,为什么回想起来列表理解中的 lambda 会覆盖自己?

In Python, why do lambdas in list comprehensions overwrite themselves in retrospect?

考虑以下代码:

def f (a):
    return 1
def g (a):
    return 2

[lambda a: i(a) for i in (f,g)][0](0)

结果是2,明明应该是1!我希望这段代码按如下方式执行。创建一个列表。将函数 f 复制到第一个索引中。将 g 复制到第二个索引中。 Fin.

为什么会这样执行?!

lambda 并没有覆盖自己,而是 i 被覆盖了。这是关于变量作用域的常见错误。试试这个:

[lambda a, i=i: i(a) for i in (f,g)][0](0)

(不同之处在于在创建 lambda 时绑定 i 的值)

另请参阅:

  • Weird behavior: Lambda inside list comprehension
  • What is “lambda binding” in Python?
  • Python lambda's binding to local values

我会稍微扩展@dsh 的回答。

当列表理解表达式

[lambda a: i(a) for i in (f,g)]

被求值,它创建了两个匿名函数,每个函数的效果是

def _______(a):
    return i(a)

但是,在对上述列表推导求值后,名称 i 绑定到其最后一次迭代值,即绑定到 g 的对象,即您的第 2 个函数。

现在,在那之后,当列表中的匿名函数之一被调用时,它访问模块全局范围内的名称 i 绑定到与 g 相同的东西是 .


编辑:哦,@dsh 也对其进行了扩展。