海象运算符:如果结果奇怪

时间:2019-07-10 10:31:41

标签: python python-3.x python-3.8

我正在和海象运算符:=玩耍(与this question相关),该运算符将在python 3.8中提供。

使用

def f(x):
    return x**3

old_list =  = list(range(9))

这按预期工作(不要介意该示例毫无意义...):

new_list = [fx for x in old_list if (fx := f(x))  in {1, 8, 343}]
# [1, 8, 343]

这是有效的并且可以运行,但是返回意外的内容:

new_list = [fx := f(x) for x in old_list if fx in {1, 8, 343}]
# []

这是怎么回事?

1 个答案:

答案 0 :(得分:3)

TL; DR您的第二个密码不是“ that”有效的:

>>> old_list = list(range(9))
>>> f = lambda x: x ** 3
>>> [fx := f(x) for x in old_list if fx in {1, 8, 343}]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <listcomp>
NameError: name 'fx' is not defined
>>> 

说明

在您的第一个列表理解[fx for x in old_list if (fx := f(x)) in {1, 8, 343}]中,fx :=在其外部创建了一个变量:

>>> old_list = list(range(9))
>>> f = lambda x: x ** 3
>>> [fx for x in old_list if (fx := f(x))  in {1, 8, 343}]
[1, 8, 343]
>>> fx
512

如果之后再运行[fx := f(x) for x in old_list if fx in {1, 8, 343}],它将像这样:

  • for x in old_list将x绑定到0
  • if fx in {1, 8, 343},fx是错误的旧512
  • 如果if为false,则不执行“选择”(左)部分,不调用f,不重新绑定fx,fx仍为512。
  • 将x分配为old_list的第二个元素,即1
  • ...

我们可以像这样仔细检查这种解释:

>>> [print("no no no") for x in old_list if fx in {1, 8, 343}]
[]

no no no不会被打印,因此这一面也不会执行(因为fx是512,不在set中)。