在列表推导式中使用if/else

1682 投票
13 回答
1989732 浏览
提问于 2025-04-16 07:31

我想把下面这个包含了if/elsefor循环转换成列表推导式。

results = []
for x in xs:
    results.append(f(x) if x is not None else '')

如果xNone,那么结果应该是'',否则就返回f(x)。我试过:

[f(x) for x in xs if x is not None else '']

但是它给了我一个SyntaxError(语法错误)。正确的写法是什么呢?


想了解... if ... else ...的相关信息,可以查看 这个链接
想知道如何根据条件来省略某些值,可以查看 这个链接,里面有[... for x in xs if x cond]的用法。
想了解在列表推导式中使用elif的情况,可以查看 这个链接

13 个回答

86

这个具体的问题在之前的回答中已经解决了,所以我想谈谈在列表推导式中使用条件语句的一般思路。

下面是一个例子,展示了如何在列表推导式中写条件语句:

X = [1.5, 2.3, 4.4, 5.4, 'n', 1.5, 5.1, 'a']     # Original list

# Extract non-strings from X to new list
X_non_str = [el for el in X if not isinstance(el, str)]  # When using only 'if', put 'for' in the beginning

# Change all strings in X to 'b', preserve everything else as is
X_str_changed = ['b' if isinstance(el, str) else el for el in X]  # When using 'if' and 'else', put 'for' in the end

注意,在第一个列表推导式 X_non_str 中,顺序是:

表达式 对于 项目 可迭代对象 如果 条件

而在最后一个列表推导式 X_str_changed 中,顺序是:

表达式1 如果 条件 否则 表达式2 对于 项目 可迭代对象

我总是觉得很难记住 表达式1 必须在 if 之前,而 表达式2 必须在 else 之后。我的脑子总想把它们放在一起,要么都在前面,要么都在后面。

我想这样设计是因为它和我们平常说的话很像,比如:“如果下雨,我想待在里面,否则我想出去。”

用简单的语言来说,上面提到的两种列表推导式可以这样理解:

只有 if 的情况:

提取苹果 对于 苹果 苹果箱 如果 苹果成熟

还有 if/else 的情况:

标记苹果 如果 苹果成熟 否则 不标记 对于 苹果 苹果箱

126

我们来用这个问题复习一些概念。我觉得先了解基础知识是很重要的,这样你才能把这些知识应用到不同的情况中。

其他回答已经给出了你问题的具体答案。我会先提供一些一般性的背景知识,然后再回答你的问题。

基础知识

if/else 语句在列表推导式中涉及两个方面:

  • 列表推导式
  • 条件表达式(也叫三元运算符)

1. 列表推导式

它们提供了一种简洁的方式来创建列表。

它的结构是:“包含表达式的括号,后面跟着一个 for 子句,然后是零个或多个 for 或 if 子句”。

案例 1

在这里我们没有条件。可迭代对象中的每个项目都会被添加到 new_list 中。

new_list = [expression for item in iterable]
new_list = [x for x in range(1, 10)]
> [1, 2, 3, 4, 5, 6, 7, 8, 9]

案例 2

在这里我们有一个条件。

示例 1

条件:只有 偶数 会被添加到 new_list 中。

new_list = [expression for item in iterable if condition == True]
new_list = [x for x in range(1, 10) if x % 2 == 0]
> [2, 4, 6, 8]

示例 2

条件:只有 偶数 且是 3 的倍数的数字会被添加到 new_list 中。

new_list = [expression for item in iterable if condition == True]
new_list = [x for x in range(1, 10) if x % 2 == 0 if x % 3 == 0]
> [6]

但是如果在 new_list 中使用了两个 if,为什么我们还是只有一个条件呢?

之前的表达式可以写成:

new_list = [x for x in range(1, 10) if x % 2 and x % 3 == 0]
> [6]

我们只使用了一个 if 语句。

这就像是这样做:

new_list = []
for x in range(1, 10):
    if x % 2 == 0 and x % 3 == 0:
        new_list.append(x)
> [6]

示例 3

为了讨论的方便,你也可以使用 or

条件:偶数 或者是 3 的倍数的数字会被添加到 new_list 中。

new_list = [x for x in range(1, 10) if x % 2 == 0 or x % 3 == 0]
> [2, 3, 4, 6, 8, 9]

案例 3

多个条件:

在这里我们需要条件表达式(也叫三元运算符)的帮助。

2. 条件表达式

什么是条件表达式?顾名思义,就是一个有条件的 Python 表达式。

<Exp1> if condition else <Exp2>

首先会评估 condition。如果 conditionTrue,那么就会评估并返回 <Exp1>。如果 conditionFalse,那么就会评估并返回 <Exp2>

一个有多个条件的条件表达式:

<Exp1> if condition else <Exp2> if condition else <Exp3>...    

来自 Real Python 的一个例子:

age = 12
s = 'minor' if age < 21 else 'adult'
> minor

变量 s 的值是根据 age 的值来决定的。

3. 带条件的列表推导式

我们把列表推导式和条件结合起来,像这样。

new_list = [<Conditional Expression> for <item> in <iterable>]

new_list = [<Exp1> if condition else <Exp2> if condition else <Exp3> for <item> in <iterable>]

条件:偶数 会被添加为 'even',数字三会被添加为 'number three',其他的会被添加为 'odd'

new_list = ['even' if x % 2 == 0 else 'number three' if x == 3 else 'odd' 
             for x in range(1, 10)]
> ['odd', 'even', 'number three', 'even', 'odd', 'even', 'odd', 'even', 'odd']

问题的答案

[f(x) for x in xs if x is not None else '']

这里我们在列表结构上有个问题:for x in xs 应该放在表达式的最后。

正确的写法是:

[f(x) if x is not None else '' for x in xs]

进一步阅读:

Python 有三元条件运算符吗?

2814

你完全可以这样做。这只是一个顺序问题:

[f(x) if x is not None else '' for x in xs]

一般来说,

[f(x) if condition else g(x) for x in sequence]

而且,对于只有 if 条件的列表推导式,

[f(x) for x in sequence if condition]

注意,这实际上使用了另一种语言结构,叫做 条件表达式,它本身并不是 推导语法的一部分,而 for…in 后面的 if 是列表推导式的一部分,用于从源可迭代对象中 筛选 元素。


条件表达式可以在你想根据某个条件选择两个表达式值的各种情况下使用。这和其他语言中的 三元运算符 ?: 的作用是一样的。例如:

value = 123
print(value, 'is', 'even' if value % 2 == 0 else 'odd')

撰写回答