Python中列表推导式的评估顺序是什么?

3

我有两个列表推导式,其中条件在不同的位置定义。

>>> [ x**2 if x%2==0 else x**3 if x%3==0 else 0 for x in range(10)]
[0, 0, 4, 27, 16, 0, 36, 0, 64, 729]

>>> [ x**2 if x%2==0 for x in range(10) ]
  File "<stdin>", line 1
    [ x**2 if x%2==0 for x in range(10) ]
                       ^
SyntaxError: invalid syntax

然而,如果我这样做:
>>> [ x**2 for x in range(10) if x%2==0 ]
[0, 4, 16, 36, 64]
>>> 

它正常工作。

现在令人困惑的部分是如何评估顺序。有什么区别吗?


否则是不可选的。 - Golden Lion
4个回答

5
你把两个不同的概念混淆了。
x**2 if x%2==0 else x**3 这样的表达式是一种条件表达式。它们可以链接在一起,但是 else必需的 - 因为这是一个自包含的表达式,它计算出一个单独、特定的值。else x**3 是必需的,因为 Python 需要知道当 x % 2 == 0 不成立时表达式的计算结果是什么。
在列表推导中,当你写类似于 [x**2 for x in range(10) if x%2==0] 的东西时,if 子句用于过滤在 range(10) 中找到的 x 值,对这些值进行计算并生成结果列表。这里没有允许使用 else,因为目的完全不同。
你可以混合和匹配:[x**2 if x%2 == 0 else x**3 for x in range(10) if x%3 == 0]。现在,if x % 3 == 0 被用来决定计算哪些 x 值的结果,而 if x%2 == 0 被用来决定是否将 x**2x**3 作为这些 x 的计算结果。

1
你混淆了两个完全不同的结构。
列表推导式的条件只能在结尾处定义,并且它们像“过滤器”一样起作用:
[ ... for ... if .... ]

你会看到的另一个结构是Python版本的三元运算符。它不是过滤器,只是根据第三个表达式的逻辑值选择其中一个表达式:

... if ... else ...

1
列表解析中的 if 可以放在任何位置,除了第一个 for 之前:[x for x in [1,2,3] if x < 2 if x < 4 for j in [x]] - falsetru
这不是一个 嵌套推导式 - falsetru

0
例如,这个:
[ x**2 if x%2==0 else x**3 if x%3==0 else 0 for x in range(10)]

这的等效形式是什么:
>>> l = []
>>> for x in range(10):
...     l.append(x**2 if x%2==0 else x**3 if x%3==0 else 0)
... 
>>> l
[0, 0, 4, 27, 16, 0, 36, 0, 64, 729]

即没有if语句,而是有一个if表达式。因此,在每一步的for中,列表始终会添加一些内容。

但是,当您这样做时:

[ x**2 for x in range(10) if x%2==0 ]

将使用if语句。并非所有步骤都会添加到列表中。

>>> l = []
>>> for x in range(10):
...     if x%2==0:
...             l.append(x**2)
... 
>>> l
[0, 4, 16, 36, 64]

0

来自文档

列表推导式由包含表达式的方括号组成,后跟一个for子句,然后是零个或多个for或if子句。结果将是一个新列表,该列表是通过在其后跟随的for和if子句的上下文中评估表达式而生成的。

因此,根据定义,iffor之后。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接