gpt4 book ai didi

python - 如何避免推导式中 Python 赋值表达式的泄漏

转载 作者:行者123 更新时间:2023-12-03 14:52:42 25 4
gpt4 key购买 nike

Effective Python书中,作者建议使用赋值表达式来避免理解中的冗余,例如:

def fun(i):
return 2 * i

result = {x: y for x in [0, 1, 2, 3] if (y := fun(x)) > 3}
代替
result = {x: fun(x) for x in [0, 1, 2, 3] if fun(x) > 3}
result具有值 {2: 4, 3: 6} .
作者指出

If a comprehension uses the walrus operator in the value part of the comprehension and doesn’t have a condition, it’ll leak the loop variable into the containing scope. [...] It’s better not to leak loop variables, so I recommend using assignment expressions only in the condition part of a comprehension.


但是,在上面的示例中, y在程序结束时设置为 6。因此,赋值表达式中的变量泄漏了,尽管它是在条件中定义的。
列表推导式也会发生同样的事情:
>>> _ = [(x, leak) for x in range(4) if (leak := 2 * x) > 3]
>>> leak
6
甚至对于生成器表达式:
>>> it = ((x, leak) for x in range(4) if (leak := 2 * x) > 3)
>>> next(it)
(2, 4)
>>> leak
4
>>> next(it)
(3, 6)
>>> leak
6
我错过了什么?有什么方法可以完全避免在推导式中的赋值表达式泄漏?

最佳答案

在 Python 中,不可能不泄漏循环变量
与 C 或 Java 等其他语言不同,Python 在 if 内没有单独的作用域。和 for块。所以当你使用 := if 中的运算符声明,for循环或列表推导式,分配的变量将
整个函数或类定义的其余部分都在范围内。这也意味着在每个 for 之后循环,循环变量仍将在范围内并包含循环最后一次迭代的值。
如果 Effective Python 的作者认为这是一件坏事,我不同意他的观点。 “泄漏”循环变量非常有用!考虑以下示例:

while line := f.readLine():
if 'Kilian' in line:
break

print('This is the first line that contains your name: ', line)
但是,此规则有一个异常(exception):在列表推导式中进行的隐式赋值有自己的作用域:
>>> [x for x in range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
这个异常(exception)可能是您的困惑的根源。这只是一种特殊情况,在使用 := 时不适用。在列表理解中。

关于python - 如何避免推导式中 Python 赋值表达式的泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64192957/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com