python - 将循环变量值绑定到 lambda
问题描述
将循环变量传递给 lambda 时,Python 没有修复它的值。
xs = ["a", "b", "c"]
print_statements: List[Callable[[], None]] = []
for x in xs:
print_statements.append(lambda: print(f"The value: {x}"))
for print_statement in print_statements:
print_statement()
// Output:
// The value: c
// The value: c
// The value: c
考虑 Java 中的相同示例:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args)
{
List<String> xs = List.of("a", "b", "c");
List<Runnable> printStatements = new ArrayList<>();
for (String x : xs)
{
printStatements.add(() -> System.out.println("The value: " + x));
}
for (Runnable printStatement : printStatements)
{
printStatement.run();
}
}
}
// Output:
// The value: a
// The value: b
// The value: c
我在 Java 方面有更多经验。因此,Java 程序的输出是我所期望的。在 Python 中,这对我来说是一个真正的问题,我想了解正在发生的事情。
- Python 示例中发生了什么?
- 似乎传递了对循环变量的引用
- 是否可能正在进行惰性评估,从而导致这种行为?
- 为什么 Python 是这样实现的?Python 开发人员背后的原因是什么?
- 您能否指出涵盖相关范围规则的 Python 文档?
- 如何更改 Python 代码以获得与 Java 示例中相同的输出
解决方案
如何更改 Python 代码以获得与 Java 示例中相同的输出
可以将外部范围变量的值绑定到 lambda 的范围:
xs = ["a", "b", "c"]
print_statements: List[Callable[[], None]] = []
for x in xs:
print_statements.append(lambda local_x=x: print(f"The value: {local_x}"))
# Output:
# The value: a
# The value: b
# The value: c
我仍然想知道为什么 Python 是这样设计的。
我刚刚注意到 Java 不会让您执行以下操作:
for (int i = 0; i < xs.size(); i++)
{
printStatements.add(() -> System.out.println("The value: " + xs.get(i)));
}
编译器抱怨:Variable used in lambda expression should be final or effectively final
然后解决这个问题
for (int i = 0; i < xs.size(); i++)
{
int finalI = i;
printStatements.add(() -> System.out.println("The value: " + xs.get(finalI)));
}
我认为这对应于 Python 代码。Python 没有那么严格,并且允许(用 Java 术语)在 lambda 中使用不是“最终或有效最终”的变量。
推荐阅读
- python - 没有名为“localstack.mock”的模块
- eclipse - Eclipse:单击任何视图即可调用文件匹配策略
- clojure - DataScript / datahike 规则不返回任何内容
- android - Kotlin,Android - 我如何在可运行文件中发布相同的可运行文件?
- python - 显示连续出现次数最多的数字
- javascript - 在 mocha post 函数上为 %s 赋值
- python - 使用返回值导入模块
- php - curl 不工作但也没有给出任何错误
- c# - 使用 C# 实现 Java 自动化的 WindowsAccessBridge
- python - 使用 Python 将字符串列合并到一组列表