在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}
。
作者指出
如果推导式在推导式的值部分使用海象运算符并且没有条件,它会将循环变量泄漏到包含范围内。[...] 最好不要泄漏循环变量,所以我建议只在理解的条件部分使用赋值表达式。
但是,在上面的示例中,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
我错过了什么?有什么方法可以完全避免在理解中的赋值表达式中泄漏?