我有两个列表推导,其中条件在不同的地方定义。
>>> [ 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]
>>>
它有效。
现在令人困惑的部分是如何评估订单。有什么区别?
答案 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**2
或x**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]