列表推导式中的条件。为什么当我使用“else”时会有所不同?

mus*_*324 0 python list-comprehension list conditional-statements

代码 A:

numbers = [2, -1, 79, 33, -45]
negative_doubled = [num * 2 for num in numbers if num < 0]
print(negative_doubled) # output is: [-2, -90]
Run Code Online (Sandbox Code Playgroud)

代码 B:

numbers = [2, -1, 79, 33, -45]
doubled = [num * 2 if num < 0 else num * 3 for num in numbers ]
print(doubled) # output is: [6, -2, 237, 99, -90]
Run Code Online (Sandbox Code Playgroud)

如您所见,if语句的位置是不同的。在代码 A 中,该if语句位于 for 循环语句之后。

他们为什么不写这样的代码?我会觉得它更直观。

numbers = [2, -1, 79, 33, -45]
negative_doubled = [num * 2 if num < 0 for num in numbers] # SyntaxError
print(negative_doubled) 
Run Code Online (Sandbox Code Playgroud)

(如您所知,这个位置是一个语法错误。)

有没有可能出现问题的情况?

blo*_*gon 6

您可以认为 Python 中的推导式始终遵循以下通用格式:

[expression for iter_var in sequence if some_condition]
Run Code Online (Sandbox Code Playgroud)

除非为 给出明确的布尔表达式some_condition,否则假定为真。

expression可以是在Python任何有效的表达,包括三元表达,下面的格式

x = val if cond else other_val
Run Code Online (Sandbox Code Playgroud)

这相当于

if cond:
    x = val
else:
    x = other_val
Run Code Online (Sandbox Code Playgroud)

一种理解是一个简单的过滤器,[x for x in seq if cond]。另一种是三元表达式[x if cond else y for _ in seq]

过滤理解的示例:

>>> [x for x in range(10) if x % 2 == 0]
[0, 2, 4, 6, 8]
Run Code Online (Sandbox Code Playgroud)

这相当于

res = []
for x in range(10):
    if x % 2 == 0:
        res.append(x)
Run Code Online (Sandbox Code Playgroud)

下面是一个三元理解的例子:

>>> [x**2 if x % 2 == 0 else x**3 for x in range(10)]
[0, 1, 4, 27, 16, 125, 36, 343, 64, 729]
Run Code Online (Sandbox Code Playgroud)

这相当于

res = []
for x in range(10):
    res.append(x**2 if x % 2 == 0 else x**3)
Run Code Online (Sandbox Code Playgroud)

这是两者结合的示例:

>>> lst = [1, "a", "b", 3, "2", 6]
>>> [x**2 if x % 2 == 0 else x**3 for x in lst if isinstance(x, int)]
[1, 27, 36]
Run Code Online (Sandbox Code Playgroud)

这相当于

res = []
for x in range(10):
    if isinstance(x, int):
        res.append(x**2 if x % 2 == 0 else x**3)
Run Code Online (Sandbox Code Playgroud)

TL; 博士

您可以将推导理解为实际上具有一个统一的结构:

[expression for iter_var in sequence if some_condition]
Run Code Online (Sandbox Code Playgroud)

theexpression可以是任何东西,甚至是一个三元表达式,它本身包含ifandelse关键字,但实际上与some_condition所有推导式所基于的都无关。

我不知道,我喝醉了,而且我觉得我在解释方面做得不好,也不想再尝试了。

  • 但OP显然“不”理解理解是如何工作的。一种对收集的值使用三元赋值表达式,一种使用过滤语句。这个答案试图解释这些差异。 (2认同)
  • @juanpa.arrivilillaga 是的,这是一个很好的答案,你可以贡献。但这不是唯一的答案。恕我直言,如果他知道两者之间的区别(它们是“不同的”“if”),那么他就不会问这个问题。 (2认同)