目 录CONTENT

文章目录

Python(二十六) 嵌套推导式与条件筛选详解

Python(二十六) 嵌套推导式与条件筛选详解

1. 什么是嵌套推导式

在学习 Python 推导式时,我们通常先接触最简单的写法。

例如,生成一个平方列表:

nums = [x * x for x in range(1, 6)]
print(nums)

输出:

[1, 4, 9, 16, 25]

这种写法只有一个 for,比较简单。

如果推导式中出现多个 for,就可以称为嵌套推导式。

例如:

result = [(x, y) for x in [1, 2] for y in [3, 4]]
print(result)

输出:

[(1, 3), (1, 4), (2, 3), (2, 4)]

它等价于下面的普通嵌套循环:

result = []

for x in [1, 2]:
    for y in [3, 4]:
        result.append((x, y))

print(result)

通俗理解:

嵌套推导式就是把嵌套 for 循环写进推导式里。

2. 什么是条件筛选

条件筛选就是在推导式中加上 if,只保留符合条件的数据。

例如,筛选偶数:

nums = [1, 2, 3, 4, 5, 6]
evens = [x for x in nums if x % 2 == 0]

print(evens)

输出:

[2, 4, 6]

它等价于:

nums = [1, 2, 3, 4, 5, 6]
evens = []

for x in nums:
    if x % 2 == 0:
        evens.append(x)

print(evens)

通俗理解:

条件筛选就是先遍历,再判断,符合条件才放进去。

3. 本节学习目标

学完这篇内容,应该能够掌握:

  1. 嵌套推导式的基本写法。
  2. 多个 for 的执行顺序。
  3. 条件筛选 if 的写法。
  4. if...else 在推导式中的写法。
  5. 二维列表的展平、筛选和转换。
  6. 嵌套列表推导式、字典推导式、集合推导式。
  7. 什么时候适合用推导式,什么时候不适合用。

4. 先复习普通推导式

4.1 列表推导式

基本语法:

[表达式 for 变量 in 可迭代对象]

示例:

nums = [x for x in range(5)]
print(nums)

输出:

[0, 1, 2, 3, 4]

4.2 带条件的列表推导式

基本语法:

[表达式 for 变量 in 可迭代对象 if 条件]

示例:

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

输出:

[0, 2, 4, 6, 8]

4.3 字典推导式

基本语法:

{键表达式: 值表达式 for 变量 in 可迭代对象}

示例:

squares = {x: x * x for x in range(1, 6)}
print(squares)

输出:

{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

4.4 集合推导式

基本语法:

{表达式 for 变量 in 可迭代对象}

示例:

chars = {ch for ch in "banana"}
print(chars)

输出可能是:

{'b', 'a', 'n'}

集合会自动去重,并且没有固定顺序。

5. 嵌套推导式的基本语法

嵌套列表推导式的常见写法:

[表达式 for 外层变量 in 外层可迭代对象 for 内层变量 in 内层可迭代对象]

例如:

result = [(x, y) for x in [1, 2] for y in [3, 4]]
print(result)

输出:

[(1, 3), (1, 4), (2, 3), (2, 4)]

等价于:

result = []

for x in [1, 2]:
    for y in [3, 4]:
        result.append((x, y))

print(result)

记忆方式:

推导式中 for 的顺序,和普通嵌套 for 循环的顺序一致。

也就是说:

[(x, y) for x in a for y in b]

对应:

for x in a:
    for y in b:
        ...

6. 嵌套推导式的执行顺序

很多初学者看见嵌套推导式会不知道从哪里开始读。

建议从第一个 for 开始读。

示例:

result = [(x, y) for x in [1, 2] for y in [3, 4]]

阅读顺序:

1. x 先取 1。
2. y 再依次取 3、4。
3. 得到 (1, 3)、(1, 4)。
4. x 再取 2。
5. y 再依次取 3、4。
6. 得到 (2, 3)、(2, 4)。

最终结果:

[(1, 3), (1, 4), (2, 3), (2, 4)]

可以把它想象成:

外层循环走一步,内层循环跑一整圈。

7. 生成所有组合

嵌套推导式最常见的用途之一,就是生成所有组合。

7.1 商品颜色和尺码组合

colors = ["红色", "蓝色"]
sizes = ["S", "M", "L"]

products = [(color, size) for color in colors for size in sizes]

print(products)

输出:

[('红色', 'S'), ('红色', 'M'), ('红色', 'L'), ('蓝色', 'S'), ('蓝色', 'M'), ('蓝色', 'L')]

等价于:

colors = ["红色", "蓝色"]
sizes = ["S", "M", "L"]

products = []

for color in colors:
    for size in sizes:
        products.append((color, size))

print(products)

7.2 坐标点组合

生成一个简单的坐标网格:

points = [(x, y) for x in range(3) for y in range(2)]
print(points)

输出:

[(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]

可以理解为:

x 有 0、1、2 三种选择。
y 有 0、1 两种选择。
总共有 3 * 2 = 6 个坐标点。

7.3 九九乘法表数据

生成九九乘法表中的表达式:

items = [f"{j}x{i}={i * j}" for i in range(1, 10) for j in range(1, i + 1)]
print(items)

输出前几个结果:

['1x1=1', '1x2=2', '2x2=4', '1x3=3', '2x3=6', '3x3=9', ...]

如果要真正打印成表格,普通循环更直观:

for i in range(1, 10):
    for j in range(1, i + 1):
        print(f"{j}x{i}={i * j}", end="\t")
    print()

教学建议:

生成数据可以用推导式。
控制输出格式更适合用普通循环。

8. 二维列表展平

二维列表是列表里面还有列表。

例如:

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

如果想把它变成一维列表:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

可以使用嵌套推导式。

8.1 展平二维列表

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

result = [num for row in matrix for num in row]

print(result)

输出:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

等价于:

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

result = []

for row in matrix:
    for num in row:
        result.append(num)

print(result)

阅读方式:

先从 matrix 中取出一行 row,
再从 row 中取出每个 num,
最后把 num 放入新列表。

8.2 展平并筛选偶数

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

evens = [num for row in matrix for num in row if num % 2 == 0]

print(evens)

输出:

[2, 4, 6, 8]

等价于:

evens = []

for row in matrix:
    for num in row:
        if num % 2 == 0:
            evens.append(num)

print(evens)

8.3 展平并转换数据

把二维列表中的所有数字扩大 10 倍:

matrix = [
    [1, 2],
    [3, 4]
]

result = [num * 10 for row in matrix for num in row]

print(result)

输出:

[10, 20, 30, 40]

8.4 展平字符串列表

words = ["hi", "abc"]

chars = [ch for word in words for ch in word]

print(chars)

输出:

['h', 'i', 'a', 'b', 'c']

等价于:

chars = []

for word in words:
    for ch in word:
        chars.append(ch)

print(chars)

9. 嵌套推导式中的条件筛选

嵌套推导式可以配合 if 条件。

语法:

[表达式 for 外层变量 in 外层对象 for 内层变量 in 内层对象 if 条件]

9.1 筛选符合条件的组合

生成两个列表中和大于 6 的组合:

a = [1, 2, 3, 4]
b = [3, 4, 5]

result = [(x, y) for x in a for y in b if x + y > 6]

print(result)

输出:

[(2, 5), (3, 4), (3, 5), (4, 3), (4, 4), (4, 5)]

等价于:

result = []

for x in a:
    for y in b:
        if x + y > 6:
            result.append((x, y))

print(result)

9.2 筛选乘积为偶数的组合

a = [1, 2, 3]
b = [4, 5, 6]

result = [(x, y) for x in a for y in b if (x * y) % 2 == 0]

print(result)

输出:

[(1, 4), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 6)]

9.3 多个条件筛选

筛选出 x < yx + y 是偶数的组合:

nums = [1, 2, 3, 4]

result = [(x, y) for x in nums for y in nums if x < y and (x + y) % 2 == 0]

print(result)

输出:

[(1, 3), (2, 4)]

也可以写成多个 if

nums = [1, 2, 3, 4]

result = [(x, y) for x in nums for y in nums if x < y if (x + y) % 2 == 0]

print(result)

输出:

[(1, 3), (2, 4)]

教学建议:

多个条件一般用 and 写在一个 if 中,更容易读。

10. 外层条件和内层条件

嵌套推导式中,if 放在不同位置,含义可能不同。

10.1 条件放在最后

result = [(x, y) for x in range(3) for y in range(3) if x != y]
print(result)

输出:

[(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]

这个 if x != y 是在内层循环后判断的。

等价于:

result = []

for x in range(3):
    for y in range(3):
        if x != y:
            result.append((x, y))

10.2 条件紧跟在外层 for 后面

result = [(x, y) for x in range(5) if x % 2 == 0 for y in range(3)]
print(result)

输出:

[(0, 0), (0, 1), (0, 2), (2, 0), (2, 1), (2, 2), (4, 0), (4, 1), (4, 2)]

等价于:

result = []

for x in range(5):
    if x % 2 == 0:
        for y in range(3):
            result.append((x, y))

意思是:

先筛选外层的 x。
只有 x 是偶数时,才执行内层 y 循环。

10.3 条件位置对结果的影响

看两个例子。

例子一:

result = [(x, y) for x in range(4) if x % 2 == 0 for y in range(3)]
print(result)

输出:

[(0, 0), (0, 1), (0, 2), (2, 0), (2, 1), (2, 2)]

例子二:

result = [(x, y) for x in range(4) for y in range(3) if y % 2 == 0]
print(result)

输出:

[(0, 0), (0, 2), (1, 0), (1, 2), (2, 0), (2, 2), (3, 0), (3, 2)]

第一个例子筛选的是 x

第二个例子筛选的是 y

教学总结:

if 放在哪个 for 后面,通常就和哪个循环层级关系更近。

不过如果写法太绕,建议改成普通循环。

11. if 筛选和 if...else 转换

这是推导式中最容易混淆的知识点。

11.1 if 筛选

语法:

[表达式 for 变量 in 可迭代对象 if 条件]

作用:

只保留满足条件的数据。

示例:

nums = [-2, -1, 0, 1, 2]
result = [x for x in nums if x > 0]

print(result)

输出:

[1, 2]

结果数量变少了。

11.2 if...else 转换

语法:

[值1 if 条件 else 值2 for 变量 in 可迭代对象]

作用:

每个数据都处理,只是根据条件决定处理结果。

示例:

nums = [-2, -1, 0, 1, 2]
result = [x if x > 0 else 0 for x in nums]

print(result)

输出:

[0, 0, 0, 1, 2]

结果数量没有变。

11.3 两种写法对比

nums = [-2, -1, 0, 1, 2]

result1 = [x for x in nums if x > 0]
result2 = [x if x > 0 else 0 for x in nums]

print(result1)
print(result2)

输出:

[1, 2]
[0, 0, 0, 1, 2]

对比表:

写法 含义 结果数量
[x for x in nums if 条件] 筛选数据 可能变少
[值1 if 条件 else 值2 for x in nums] 转换数据 通常不变

12. 嵌套推导式中的 if...else

if...else 可以出现在嵌套推导式的表达式位置。

12.1 标记坐标是否在对角线上

result = ["对角线" if x == y else "普通点" for x in range(3) for y in range(3)]

print(result)

输出:

['对角线', '普通点', '普通点', '普通点', '对角线', '普通点', '普通点', '普通点', '对角线']

如果希望看得更清楚,可以保留坐标:

result = [((x, y), "对角线" if x == y else "普通点") for x in range(3) for y in range(3)]

print(result)

输出:

[((0, 0), '对角线'), ((0, 1), '普通点'), ((0, 2), '普通点'), ((1, 0), '普通点'), ((1, 1), '对角线'), ((1, 2), '普通点'), ((2, 0), '普通点'), ((2, 1), '普通点'), ((2, 2), '对角线')]

12.2 把二维列表中的奇数改成 0

matrix = [
    [1, 2, 3],
    [4, 5, 6]
]

result = [num if num % 2 == 0 else 0 for row in matrix for num in row]

print(result)

输出:

[0, 2, 0, 4, 0, 6]

12.3 同时使用 if...else 和筛选 if

可以同时使用 if...else 和后置 if

例如:

nums = [-3, -2, -1, 0, 1, 2, 3]

result = ["正数" if x > 0 else "负数" for x in nums if x != 0]

print(result)

输出:

['负数', '负数', '负数', '正数', '正数', '正数']

阅读顺序:

1. for x in nums 取出每个 x。
2. if x != 0 先过滤掉 0。
3. "正数" if x > 0 else "负数" 对剩余数据分类。

这类写法对初学者有一定难度,教学时建议先拆成普通循环。

等价写法:

nums = [-3, -2, -1, 0, 1, 2, 3]
result = []

for x in nums:
    if x != 0:
        if x > 0:
            result.append("正数")
        else:
            result.append("负数")

print(result)

13. 嵌套列表推导式生成二维列表

前面讲的是把二维列表变成一维列表。

现在看反过来的情况:生成二维列表。

13.1 生成 3 行 4 列的二维列表

matrix = [[0 for col in range(4)] for row in range(3)]

print(matrix)

输出:

[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

这个推导式要这样读:

外层 for row in range(3) 控制生成 3 行。
内层 [0 for col in range(4)] 控制每一行有 4 个 0。

等价于:

matrix = []

for row in range(3):
    line = []
    for col in range(4):
        line.append(0)
    matrix.append(line)

print(matrix)

13.2 生成带行列值的二维列表

matrix = [[row * 10 + col for col in range(4)] for row in range(3)]

print(matrix)

输出:

[[0, 1, 2, 3], [10, 11, 12, 13], [20, 21, 22, 23]]

13.3 生成乘法表数据

table = [[i * j for j in range(1, 6)] for i in range(1, 6)]

print(table)

输出:

[[1, 2, 3, 4, 5], [2, 4, 6, 8, 10], [3, 6, 9, 12, 15], [4, 8, 12, 16, 20], [5, 10, 15, 20, 25]]

每一行可以理解为一个数字对应的乘法结果。

14. 生成二维列表的常见坑

在 Python 中,生成二维列表有一个非常经典的坑。

14.1 不推荐的写法

matrix = [[0] * 3] * 4
print(matrix)

输出:

[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

看起来没问题。

但是如果修改其中一个元素:

matrix[0][0] = 1
print(matrix)

输出:

[[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]

问题出现了:每一行的第一个元素都变成了 1

原因是:

[[0] * 3] * 4 复制的是同一个小列表的引用。
多行看起来不同,实际上指向同一个列表。

14.2 推荐的写法

使用嵌套列表推导式:

matrix = [[0 for col in range(3)] for row in range(4)]

matrix[0][0] = 1

print(matrix)

输出:

[[1, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

这样每一行都是独立的列表。

教学记忆:

创建二维列表,推荐使用嵌套列表推导式。
不要简单使用 [[0] * 列数] * 行数。

15. 嵌套字典推导式

字典推导式也可以配合嵌套循环和条件筛选。

15.1 生成坐标和值的字典

points = {(x, y): x + y for x in range(3) for y in range(3)}

print(points)

输出:

{(0, 0): 0, (0, 1): 1, (0, 2): 2, (1, 0): 1, (1, 1): 2, (1, 2): 3, (2, 0): 2, (2, 1): 3, (2, 2): 4}

这里:

键是坐标 (x, y)。
值是 x + y。

15.2 只保留符合条件的键值对

points = {(x, y): x * y for x in range(4) for y in range(4) if x * y > 3}

print(points)

输出:

{(2, 2): 4, (2, 3): 6, (3, 2): 6, (3, 3): 9}

15.3 字典推导式展开嵌套数据

假设有学生和课程成绩:

students = {
    "张三": {"语文": 90, "数学": 85},
    "李四": {"语文": 76, "数学": 92}
}

想变成:

{
    ("张三", "语文"): 90,
    ("张三", "数学"): 85,
    ("李四", "语文"): 76,
    ("李四", "数学"): 92
}

可以写:

students = {
    "张三": {"语文": 90, "数学": 85},
    "李四": {"语文": 76, "数学": 92}
}

result = {
    (name, subject): score
    for name, subjects in students.items()
    for subject, score in subjects.items()
}

print(result)

输出:

{('张三', '语文'): 90, ('张三', '数学'): 85, ('李四', '语文'): 76, ('李四', '数学'): 92}

这种写法适合有一定基础后再讲。

16. 嵌套集合推导式

集合推导式也可以嵌套使用。

集合特点:

自动去重,无固定顺序。

16.1 提取二维列表中的不同数字

matrix = [
    [1, 2, 2],
    [3, 3, 4],
    [4, 5, 5]
]

result = {num for row in matrix for num in row}

print(result)

输出:

{1, 2, 3, 4, 5}

16.2 提取多个单词中的不同字符

words = ["hello", "python"]

chars = {ch for word in words for ch in word}

print(chars)

输出可能是:

{'h', 'e', 'l', 'o', 'p', 'y', 't', 'n'}

16.3 筛选并去重

matrix = [
    [1, 2, 3],
    [2, 4, 6],
    [3, 6, 9]
]

evens = {num for row in matrix for num in row if num % 2 == 0}

print(evens)

输出:

{2, 4, 6}

注意:

列表推导式保留重复元素。
集合推导式会自动去重。

17. 多层嵌套推导式

推导式中可以出现三层甚至更多层循环。

例如:

result = [(x, y, z) for x in [1, 2] for y in [3, 4] for z in [5, 6]]
print(result)

输出:

[(1, 3, 5), (1, 3, 6), (1, 4, 5), (1, 4, 6), (2, 3, 5), (2, 3, 6), (2, 4, 5), (2, 4, 6)]

等价于:

result = []

for x in [1, 2]:
    for y in [3, 4]:
        for z in [5, 6]:
            result.append((x, y, z))

print(result)

但是教学和实际开发中要注意:

超过两层嵌套时,推导式很容易变得难读。

如果学生读起来吃力,应该改成普通循环。

18. 推导式中的多个 if

推导式可以有多个 if

nums = range(1, 21)

result = [x for x in nums if x % 2 == 0 if x % 3 == 0]

print(result)

输出:

[6, 12, 18]

它等价于:

nums = range(1, 21)
result = []

for x in nums:
    if x % 2 == 0:
        if x % 3 == 0:
            result.append(x)

print(result)

也等价于:

result = [x for x in range(1, 21) if x % 2 == 0 and x % 3 == 0]

教学建议:

简单多个条件,用 and 更直观。
有明显层级关系时,可以使用多个 if。

19. 推导式中的函数调用

推导式中的表达式可以调用函数。

19.1 使用函数处理数据

def clean_name(name):
    return name.strip()

names = [" 张三 ", " 李四", "王五 "]

result = [clean_name(name) for name in names]

print(result)

输出:

['张三', '李四', '王五']

19.2 使用函数判断条件

def is_valid_score(score):
    return 0 <= score <= 100

scores = [90, 120, 85, -5, 60]

result = [score for score in scores if is_valid_score(score)]

print(result)

输出:

[90, 85, 60]

教学建议:

如果推导式里的判断条件太长,可以封装成函数,让代码更清楚。

20. 推导式与可读性

推导式的优点是简洁。

但简洁不等于越短越好。

20.1 适合用推导式的情况

适合:

squares = [x * x for x in range(10)]

适合:

evens = [x for x in nums if x % 2 == 0]

适合:

points = [(x, y) for x in range(3) for y in range(3)]

这些逻辑都比较简单,使用推导式很清楚。

20.2 不适合用推导式的情况

不推荐:

result = [
    "优秀" if score >= 90 else "良好" if score >= 80 else "及格" if score >= 60 else "不及格"
    for row in all_scores
    for score in row
    if score is not None
]

虽然可以运行,但读起来比较费劲。

更推荐:

result = []

for row in all_scores:
    for score in row:
        if score is not None:
            if score >= 90:
                result.append("优秀")
            elif score >= 80:
                result.append("良好")
            elif score >= 60:
                result.append("及格")
            else:
                result.append("不及格")

教学总结:

一眼能看懂,用推导式。
需要想半天,改成普通循环。

21. 常见错误和注意事项

21.1 把 for 的顺序写反

错误示例:

matrix = [[1, 2], [3, 4]]

result = [num for num in row for row in matrix]  # 错误

原因是:

row 还没有被定义,就先使用了 row。

正确写法:

matrix = [[1, 2], [3, 4]]

result = [num for row in matrix for num in row]

print(result)

输出:

[1, 2, 3, 4]

21.2 分不清筛选 if 和 if...else

筛选:

[x for x in nums if x > 0]

转换:

[x if x > 0 else 0 for x in nums]

记忆:

后面的 if 用来筛选。
前面的 if...else 用来二选一生成结果。

21.3 嵌套太深导致难读

不推荐:

result = [(a, b, c, d) for a in A for b in B for c in C for d in D if a + b + c + d > 10]

更推荐写成普通循环,或者拆成多个步骤。

21.4 集合推导式会去重

nums = [1, 1, 2, 2, 3]
result = {x for x in nums}

print(result)

输出:

{1, 2, 3}

如果需要保留重复数据,不要使用集合推导式。

21.5 集合没有固定顺序

result = {x for x in [3, 1, 2]}
print(result)

输出顺序不一定是:

{3, 1, 2}

如果需要固定顺序,请使用列表推导式。

21.6 字典推导式要注意键重复

words = ["apple", "ant", "banana", "book"]

result = {word[0]: word for word in words}

print(result)

输出可能是:

{'a': 'ant', 'b': 'book'}

原因是:

字典的键不能重复。
后面的值会覆盖前面的值。

21.7 不要用推导式只为了执行动作

不推荐:

[print(x) for x in range(5)]

推荐:

for x in range(5):
    print(x)

推导式主要用于生成新数据,不适合只用来打印、写文件、修改外部状态。

21.8 大数据量时注意内存

列表推导式会一次性生成完整列表。

result = [x for x in range(10000000)]

如果数据量特别大,会占用较多内存。

这种情况下可以考虑生成器表达式:

result = (x for x in range(10000000))

不过对初学者来说,先掌握列表、字典、集合推导式即可。

21.9 圆括号不是元组推导式

result = (x * x for x in range(5))
print(result)

输出类似:

<generator object <genexpr> at 0x...>

这不是元组,而是生成器表达式。

如果想生成元组,要写:

result = tuple(x * x for x in range(5))
print(result)

输出:

(0, 1, 4, 9, 16)

22. 综合案例

22.1 从二维成绩表中筛选及格成绩

scores = [
    [90, 58, 76],
    [45, 88, 92],
    [60, 59, 100]
]

passed = [score for row in scores for score in row if score >= 60]

print(passed)

输出:

[90, 76, 88, 92, 60, 100]

22.2 把二维成绩表中的不及格分数改为 0

scores = [
    [90, 58, 76],
    [45, 88, 92],
    [60, 59, 100]
]

result = [[score if score >= 60 else 0 for score in row] for row in scores]

print(result)

输出:

[[90, 0, 76], [0, 88, 92], [60, 0, 100]]

注意:

这里保留了二维结构。
外层推导式生成每一行。
内层推导式处理每一行中的每个分数。

22.3 找出两个班共同喜欢的课程组合

假设每个学生可以选择多个课程:

students = {
    "张三": ["Python", "Java"],
    "李四": ["Python", "C++"],
    "王五": ["Java", "C++"]
}

result = [(name, course) for name, courses in students.items() for course in courses]

print(result)

输出:

[('张三', 'Python'), ('张三', 'Java'), ('李四', 'Python'), ('李四', 'C++'), ('王五', 'Java'), ('王五', 'C++')]

22.4 统计所有学生选择过的不同课程

students = {
    "张三": ["Python", "Java"],
    "李四": ["Python", "C++"],
    "王五": ["Java", "C++"]
}

courses = {course for course_list in students.values() for course in course_list}

print(courses)

输出:

{'Python', 'Java', 'C++'}

集合推导式会自动去重。

22.5 生成学生课程编号字典

students = {
    "张三": ["Python", "Java"],
    "李四": ["Python", "C++"]
}

result = {
    f"{name}-{course}": len(course)
    for name, courses in students.items()
    for course in courses
}

print(result)

输出:

{'张三-Python': 6, '张三-Java': 4, '李四-Python': 6, '李四-C++': 3}

23. 课堂练习

练习 1:生成所有坐标点

请使用嵌套列表推导式生成以下坐标:

[(0, 0), (0, 1), (1, 0), (1, 1)]

参考答案:

points = [(x, y) for x in range(2) for y in range(2)]
print(points)

练习 2:展平二维列表

有如下二维列表:

matrix = [[1, 2], [3, 4], [5, 6]]

请把它变成一维列表:

[1, 2, 3, 4, 5, 6]

参考答案:

matrix = [[1, 2], [3, 4], [5, 6]]
result = [num for row in matrix for num in row]

print(result)

练习 3:筛选二维列表中的偶数

matrix = [[1, 2, 3], [4, 5, 6]]

请筛选出所有偶数。

参考答案:

matrix = [[1, 2, 3], [4, 5, 6]]
evens = [num for row in matrix for num in row if num % 2 == 0]

print(evens)

练习 4:生成乘积大于 10 的组合

a = [1, 2, 3, 4]
b = [3, 4, 5]

请生成所有乘积大于 10 的组合。

参考答案:

a = [1, 2, 3, 4]
b = [3, 4, 5]

result = [(x, y) for x in a for y in b if x * y > 10]

print(result)

练习 5:生成 3 行 3 列的二维列表

请生成:

[[0, 0, 0], [0, 0, 0], [0, 0, 0]]

参考答案:

matrix = [[0 for col in range(3)] for row in range(3)]
print(matrix)

练习 6:把不及格成绩改成 0

scores = [[90, 58], [76, 45]]

请把不及格成绩改成 0,并保留二维结构。

参考答案:

scores = [[90, 58], [76, 45]]

result = [[score if score >= 60 else 0 for score in row] for row in scores]

print(result)

练习 7:提取不同字符

words = ["hello", "python"]

请用集合推导式提取所有不同字符。

参考答案:

words = ["hello", "python"]

chars = {ch for word in words for ch in word}

print(chars)

练习 8:生成坐标字典

请生成如下形式的字典:

{
    (0, 0): 0,
    (0, 1): 1,
    (1, 0): 1,
    (1, 1): 2
}

参考答案:

result = {(x, y): x + y for x in range(2) for y in range(2)}
print(result)

练习 9:筛选非空姓名

names = [[" 张三 ", ""], [" 李四", "   "], ["王五"]]

请把二维列表中的姓名取出,去掉空格,并过滤空字符串。

参考答案:

names = [[" 张三 ", ""], [" 李四", "   "], ["王五"]]

result = [name.strip() for row in names for name in row if name.strip()]

print(result)

练习 10:判断代码是否合适

下面代码是否推荐?

[print(x) for x in range(5)]

参考答案:

不推荐。
推导式主要用于生成新数据。
如果只是打印,应该使用普通 for 循环。

推荐写法:

for x in range(5):
    print(x)

24. 课堂总结

嵌套推导式和条件筛选可以让我们用较短的代码处理复杂数据。

一句话总结:

嵌套推导式就是把嵌套 for 循环写进推导式中。
条件筛选就是用 if 保留符合条件的数据。

常用写法:

[表达式 for x in 数据 if 条件]
[表达式 for x in 数据1 for y in 数据2]
[表达式 for x in 数据1 for y in 数据2 if 条件]
[值1 if 条件 else 值2 for x in 数据]
[[表达式 for 内层变量 in 内层数据] for 外层变量 in 外层数据]

教学记忆口诀:

先看 for,后看 if,
多个 for,顺序读。
后置 if 是筛选,
前置 if else 是转换。
嵌套太深别硬写,
普通循环更清楚。

最后记住一个原则:

推导式适合简单、清晰的数据生成和筛选。
如果代码看起来绕,就大胆改回普通 for 循环。
0
博主关闭了当前页面的评论