如何在python中以及以什么顺序评估列表推导

时间:2014-09-14 08:35:50

标签: python list-comprehension

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

>>> [ 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]
>>> 

它有效。

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

4 个答案:

答案 0 :(得分:4)

这里有两个不同的概念。

x**2 if x%2==0 else x**3这样的表达式是条件表达式。它们可以被链接,但else 不是可选的 - 因为这是一个自包含的表达式,其值为单个特定值。 else x**3是必需的,因为只要不是x % 2 == 0的情况,Python就必须知道表达式的计算结果。

列表理解中,当您编写[x**2 for x in range(10) if x%2==0]之类的内容时,if子句用于过滤 x找到的值in range(10)for计算结果列表的哪些元素。这里不允许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 :(得分:1)

你混淆了两种完全不同的结构。

列表推导的条件只能在最后一次定义,并且它们就像过滤器

[ ... for ... if .... ]

您看到的另一个构造是ternary operator的python版本。它不是过滤器,只是根据第三个表达式的逻辑值选择其中一个表达式:

... if ... else ...

答案 2 :(得分:0)

来自docs

  

列表推导由包含表达式的括号组成   然后是for子句,然后是零或更多for或if子句。该   结果将是评估表达式得到的新列表   跟随它的for和if条款的上下文。

因此,根据定义,if位于for之后。

答案 3 :(得分: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]