Python lambda 和作用域

发布于 2024-08-15 10:16:05 字数 228 浏览 1 评论 0原文

给定这段代码:

funcs = []
for x in range(3):
    funcs.append(lambda: x)
print [f() for f in funcs]

我希望它打印 [0, 1, 2],但它却打印 [2, 2, 2]。关于 lambda 如何与作用域一起工作,我是否遗漏了一些基本的东西?

Given this snippet of code:

funcs = []
for x in range(3):
    funcs.append(lambda: x)
print [f() for f in funcs]

I would expect it to print [0, 1, 2], but instead it prints [2, 2, 2]. Is there something fundamental I'm missing about how lambdas work with scope?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

殤城〤 2024-08-22 10:16:05

这是 Python 中常见的问题。基本上,作用域是这样的:当调用 f() 时,它将使用 x 的当前值,而不是当前位置的 x 值。 lambda 形成的时间。有一个标准的解决方法:

funcs = []
for x in range(10):
funcs.append(lambda x=x: x)
print [f() for f in funcs]

使用lambda x = x检索并保存x的当前值。

This is a frequent question in Python. Basically the scoping is such that when f() is called, it will use the current value of x, not the value of x at the time the lambda is formed. There is a standard workaround:

funcs = []
for x in range(10):
funcs.append(lambda x=x: x)
print [f() for f in funcs]

The use of lambda x = x retrieves and saves the current value of x.

我做我的改变 2024-08-22 10:16:05

x 绑定到模块级 x(for 循环留下的)。

更清楚一点:

funcs = []

for x in range(10):
    funcs.append(lambda: x)

x = 'Foo'

print [f() for f in funcs]

# Prints ['Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo']

x is bound to the module-level x (which is left over from the for loop).

A little clearer:

funcs = []

for x in range(10):
    funcs.append(lambda: x)

x = 'Foo'

print [f() for f in funcs]

# Prints ['Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo']

你知道答案:是的。 ;) 不过,请放心,因为这对于初露头角的 Python 爱好者来说是一个非常常见的发现。当您定义一个引用未在该函数内“创建”的变量的函数或 lambda 时,它会在这些变量上创建一个闭包。效果是您在调用函数时获得变量的值,而不是定义时的值。 (您期待的是后者。)

有几种方法可以解决这个问题。第一种是绑定额外的变量:

funcs = []
for x in range(10):
    funcs.append(lambda x=x: x)
print [f() for f in funcs]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

第二种方法更正式一些:

from functools import partial
funcs = []
for x in range(10):
    funcs.append(partial(lambda x: x, x))
print [f() for f in funcs]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

You know the answer: yes. ;) Take comfort, however, as this is a very common discovery for budding pythonistas. When you define a function or lambda that references variables not "created" inside that function, it creates a closure over the variables. The effect is that you get the value of the variable when calling the function, not the value at definition time. (You were expecting the latter.)

There are a few ways to deal with this. First is binding extra variables:

funcs = []
for x in range(10):
    funcs.append(lambda x=x: x)
print [f() for f in funcs]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

The second way is a little more formal:

from functools import partial
funcs = []
for x in range(10):
    funcs.append(partial(lambda x: x, x))
print [f() for f in funcs]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文