什么叫列表推导式?
本文最后更新于5 天前,其中的信息可能已经过时,如有错误请发送邮件到184874483@qq.com

列表推导式,英文叫 list comprehension
它的作用可以先用一句最直白的话来说:

把“循环取值 + 按条件筛选 + 放进列表”这几步,合并成一行来写。

你给的这两段代码,本质上做的是 同一件事
把所有满足 i + j + k != n[i, j, k] 放进列表里,最后打印出来。

也就是说:

  • 第一段是 列表推导式写法
  • 第二段是 普通 for 循环 + append 写法

它们的结果是一样的,只是写法不同。


先看这两段代码分别在做什么

第一段:列表推导式写法

if __name__ == '__main__':
    x = int(input())
    y = int(input())
    z = int(input())
    n = int(input())

    result = [
        [i, j, k]
        for i in range(x + 1)
        for j in range(y + 1)
        for k in range(z + 1)
        if i + j + k != n
    ]

    print(result)

这段代码的意思是:

  1. 依次取 i
  2. 再依次取 j
  3. 再依次取 k
  4. 判断 i + j + k != n
  5. 如果条件成立,就把 [i, j, k] 放进 result

第二段:普通 for 循环写法

if __name__ == '__main__':
    x = int(input())
    y = int(input())
    z = int(input())
    n = int(input())

    result = []

    for i in range(x + 1):
        for j in range(y + 1):
            for k in range(z + 1):
                if i + j + k != n:
                    result.append([i, j, k])

    print(result)

这段代码的意思是完全一样的,只不过它把过程一步一步展开写出来了:

  1. 先准备一个空列表 result = []
  2. 三层循环依次取 ijk
  3. 如果 i + j + k != n
  4. 就执行 result.append([i, j, k])
  5. 最后打印整个列表

列表推导式的基本语法

最基础的模板可以先记这个:

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

例如:

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

结果是:

[0, 1, 2, 3, 4]

这里:

  • x 是每次取出来的值
  • for x in range(5) 表示循环
  • 最前面的 x 表示“把什么东西放进列表里”

如果还要加条件,就变成:

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

例如:

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

结果是:

[0, 2, 4]

这表示:

  • range(5) 里一个个取 x
  • 只有当 x % 2 == 0
  • 才把 x 放进列表

这道题里的列表推导式怎么拆开理解

这句:

result = [
    [i, j, k]
    for i in range(x + 1)
    for j in range(y + 1)
    for k in range(z + 1)
    if i + j + k != n
]

可以按“翻译成人话”的方式理解:

“我要生成一个列表。
列表里的每个元素都是 [i, j, k]
其中 i0xj0yk0z
但不是所有组合都要,只要那些满足 i + j + k != n 的组合。”


它和普通 for 循环到底有什么区别?

相同点

最重要的一点先说清楚:

它们最终结果没有区别。

也就是:

  • 得到的 result 一样
  • print(result) 输出一样
  • 完成的任务一样

不同点 1:写法紧凑程度不同

列表推导式更短,更紧凑。

普通循环写法更长,但步骤更清楚。

对比一下:

列表推导式

result = [[i, j, k] for i in range(x + 1) for j in range(y + 1) for k in range(z + 1) if i + j + k != n]

普通循环

result = []

for i in range(x + 1):
    for j in range(y + 1):
        for k in range(z + 1):
            if i + j + k != n:
                result.append([i, j, k])

所以可以这样理解:

  • 列表推导式像压缩版
  • 普通循环像展开版

不同点 2:初学者的理解难度不同

对于初学者来说,通常是:

  • 普通 for 循环更容易理解
  • 列表推导式更容易写得“看起来短,但脑子转不过来”

因为普通循环把过程分得很清楚:

  1. 先创建空列表
  2. 再循环
  3. 再判断
  4. 再追加元素

而列表推导式把这些步骤合在一起了,所以读起来更像“浓缩表达”。

因此,对初学者最实用的建议是:

先把普通 for 循环写明白,再去学列表推导式。

因为列表推导式并不是新的逻辑,它只是把老逻辑换了一种更紧凑的写法。


不同点 3:思考方式不同

普通循环更适合“边想边写”。

列表推导式更适合“我已经非常清楚自己要生成什么列表”。

也就是说:

  • 如果你还在摸索逻辑,用普通循环更稳
  • 如果你已经知道“从哪里取值、满足什么条件、放什么进去”,就可以用列表推导式简化

不同点 4:变量作用范围有一点细节差别

这一点你现在不用强记,但可以稍微知道一下。

在 Python 3 里:

  • 普通 for 循环里的变量,循环结束后通常还可以继续用
  • 列表推导式里的变量,作用范围更收一些

例如:

for i in range(3):
    pass

print(i)

这里通常还能打印出 2

但列表推导式里那个 i,一般不会这样保留下来给外面直接用。

这不是你当前阶段最关键的点,但说明它们不仅是“长短不同”,内部规则也不是 100% 完全一样。

不过在你现在这道题里,这个区别几乎不影响使用。


从思路到代码:为什么它们其实是同一种逻辑?

你可以先只想“人的思路”,不要急着想代码。

这道题的思路其实是:

  1. 我要找出所有 (i, j, k) 的组合
  2. i 的范围是 0x
  3. j 的范围是 0y
  4. k 的范围是 0z
  5. 如果某个组合满足 i + j + k != n
  6. 就把它保存下来

把这个思路翻译成普通循环

因为“一个个找组合”,所以要用循环:

for i in range(x + 1):
    for j in range(y + 1):
        for k in range(z + 1):

因为“符合条件才保存”,所以要加判断:

if i + j + k != n:

因为“保存到列表里”,所以要先有一个空列表,再 append

result = []
result.append([i, j, k])

这就得到了普通写法。


再把普通循环压缩成列表推导式

普通写法里最核心的一句是:

result.append([i, j, k])

也就是说,放进去的内容是 [i, j, k]

那么列表推导式最前面就写这个:

[i, j, k]

后面再补上“这些值从哪里来”:

for i in range(x + 1)
for j in range(y + 1)
for k in range(z + 1)

最后再补上“筛选条件”:

if i + j + k != n

于是就成了:

[
    [i, j, k]
    for i in range(x + 1)
    for j in range(y + 1)
    for k in range(z + 1)
    if i + j + k != n
]

所以你一定要抓住这个本质:

列表推导式不是新东西,它只是把 for + if + append 合并写了。


一个最小例子,专门看懂列表推导式

普通写法

result = []

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

print(result)

输出:

[0, 2, 4]

列表推导式写法

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

输出也是:

[0, 2, 4]

这两段代码的区别,和你那道题的区别是同一个道理。


那初学时应该优先用哪一种?

对于你现在这个阶段,我建议这样用:

当你还没完全想清楚时

先写普通循环:

result = []

for ...
    for ...
        if ...
            result.append(...)

因为这种写法最容易检查:

  • 循环范围对不对
  • 条件对不对
  • 加进去的元素对不对

当你已经很清楚逻辑时

再改成列表推导式。

因为这时候你已经知道:

  • 我要生成什么元素
  • 元素来自哪些循环
  • 哪些情况要保留

那么就可以压缩成一行。


常见错误与易混点

1. 忘记 append() 和“直接生成列表”的区别

普通循环需要手动加:

result.append(...)

列表推导式不需要 append(),因为它本身就在创建列表。

错误写法像这样:

result = [append(x) for x in range(5)]

这是不对的。


2. 把顺序写乱

列表推导式里顺序通常是:

[结果表达式 for ... for ... if ...]

不是:

[for ... if ... 结果表达式]

最前面一定先写“放进列表的内容”。


3. 嵌套太多以后读不懂

像这题有三层循环,已经比简单题复杂了。
初学时如果一眼看不懂,完全正常。

这时候最好的办法不是硬背,而是:

先写普通循环,再把它一层一层翻译成列表推导式。


4. 误以为“列表推导式更高级,所以必须用它”

不是这样。

对于初学者来说,代码最重要的是:

  • 自己能看懂
  • 自己能改对
  • 自己能排错

所以很多时候,普通循环反而更合适。


这道题可以这样记忆

这两段代码的关系,可以直接记成一句话:

列表推导式 = 普通 for 循环 + 条件判断 + append 的简写形式。

再具体一点:

result = [
    表达式
    for ...
    for ...
    if 条件
]

等价于:

result = []

for ...
    for ...
        if 条件:
            result.append(表达式)

这就是最核心的对应关系。


本节小结

这次最需要带走的,不是“背会列表推导式长什么样”,而是理解它和普通循环之间的关系。

可以把它总结成三句话:

  1. 列表推导式是用来快速生成列表的。
  2. 它本质上就是把 for 循环、if 条件、append 合并写在一起。
  3. 你这两段代码结果一样,区别主要只是写法不同。

对于初学者来说,最推荐的学习顺序是:

先会普通循环写法,再学会把它改写成列表推导式。

这样以后看到复杂一点的推导式,也不会慌,因为你知道它本质上只是“展开版 for 循环的缩写”。


练习

把下面这段普通写法,改成列表推导式:

result = []

for x in range(10):
    if x % 2 == 1:
        result.append(x * 2)

print(result)

提示

先不要急着一口气写出来,先分三步想:

  1. 最终放进列表的内容是什么?
  2. 值是从哪里来的?
  3. 什么条件下才放进去?

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇