Python列表推导式

一、前言

在 Python 中,如果你想创建一个新列表,最"新手"的写法可能是:

python 复制代码
squares = []
for x in range(10):
    squares.append(x ** 2)

但 Python 老手会这样写:

python 复制代码
squares = [x ** 2 for x in range(10)]

这就是------列表推导式(List Comprehension)

它不仅是语法糖,更是 Python 哲学"简洁优于复杂"的完美体现。

但你真的会用吗?

  • 如何在推导式中加 if 条件?
  • 能否实现双重循环(如矩阵展平)?
  • 推导式和 map()/filter() 谁更快?
  • 什么时候不该用推导式?

本文将带你: ✅ 掌握列表推导式的 5 种核心写法

✅ 学会嵌套、条件、多表达式等高级技巧

✅ 理解其性能优势与内存效率

✅ 避开可读性差、逻辑混乱等陷阱

✅ 写出既快又美的 Pythonic 代码


二、基础语法:从 for 到推导式

通用格式

python 复制代码
[expression for item in iterable]

示例对比

传统写法 列表推导式
py<br>res = []<br>for i in range(5):<br>&nbsp;&nbsp;res.append(i*2) py<br>res = [i*2 for i in range(5)]

结果:[0, 2, 4, 6, 8]

优势:代码行数减少 50%,意图更清晰。


三、带条件过滤:if 的妙用

1. 后置条件(最常用)

python 复制代码
# 只保留偶数的平方
evens = [x ** 2 for x in range(10) if x % 2 == 0]
# 结果:[0, 4, 16, 36, 64]

2. 条件表达式(三元运算)

python 复制代码
# 奇数变负,偶数不变
transformed = [x if x % 2 == 0 else -x for x in range(5)]
# 结果:[0, -1, 2, -3, 4]

🔍 注意区别

  • if 在末尾 → 过滤元素
  • if-else 在开头 → 转换值

四、嵌套循环:处理多维数据

1. 双重循环(展平二维列表)

python 复制代码
matrix = [[1, 2, 3], [4, 5, 6]]
flattened = [num for row in matrix for num in row]
# 结果:[1, 2, 3, 4, 5, 6]

📌 执行顺序 :从左到右,外层在前,内层在后

等价于:

python 复制代码
for row in matrix:
    for num in row:
        ...

2. 生成笛卡尔积

python 复制代码
colors = ['red', 'blue']
sizes = ['S', 'M']
combinations = [f"{c}-{s}" for c in colors for s in sizes]
# 结果:['red-S', 'red-M', 'blue-S', 'blue-M']

五、高级技巧:不止于列表

技巧 1:结合函数调用

python 复制代码
words = ['hello', 'WORLD']
lower_words = [w.lower() for w in words]
# ['hello', 'world']

技巧 2:处理字典或对象

python 复制代码
students = [{'name': 'Alice', 'score': 90}, {'name': 'Bob', 'score': 85}]
names = [s['name'] for s in students if s['score'] > 85]
# ['Alice']

技巧 3:生成索引-值对(替代 enumerate

python 复制代码
data = ['a', 'b', 'c']
indexed = [(i, v) for i, v in enumerate(data)]
# [(0, 'a'), (1, 'b'), (2, 'c')]

六、性能对比:为什么推导式更快?

我们用 timeit 测试三种方式生成 [x**2 for x in range(10000)]

方法 平均耗时(1000次) 说明
for + append() ~1.8 ms 每次调用 append 有函数开销
map(lambda x: x**2, ...) ~1.5 ms C 层优化,但 lambda 有开销
列表推导式 ~1.2 ms 最快!底层用 C 实现,无函数调用

结论
列表推导式不仅更简洁,通常也更快!

💡 原因:CPython 对推导式做了专门优化,避免了方法查找和函数调用。


七、常见误区与避坑指南

❌ 误区 1:过度嵌套导致可读性差

python 复制代码
# 难以理解!
result = [func(x, y, z) for x in A for y in B if cond(x) for z in C if cond2(z)]

✅ 建议:超过两层嵌套,或逻辑复杂时,改用普通 for 循环


❌ 误区 2:在推导式中执行副作用操作

python 复制代码
# 危险!不要这样做
[print(x) for x in range(5)]  # 用列表推导式只是为了 print?

✅ 正确:副作用操作(如 print, write)应使用普通循环。

🌟 黄金法则
推导式用于"构建新数据",而非"执行动作"。


❌ 误区 3:误以为推导式节省内存

python 复制代码
huge_list = [x for x in range(10**7)]  # 仍会占用大量内存!

✅ 如果内存敏感,改用生成器表达式(小括号):

python 复制代码
huge_gen = (x for x in range(10**7))  # 惰性求值,几乎不占内存

❌ 误区 4:变量泄漏(仅 Python <3.0)

⚠️ 在 Python 2 中,推导式的循环变量会泄漏到外层作用域。
但在 Python 3+ 中已修复!

python 复制代码
[x for x in range(3)]
print(x)  # NameError: name 'x' is not defined(Python 3 安全)

八、与其他推导式的对比

Python 还支持:

  • 集合推导式{x for x in ...}
  • 字典推导式{k: v for k, v in ...}
  • 生成器表达式(x for x in ...)
python 复制代码
# 字典推导式:反转键值
original = {'a': 1, 'b': 2}
reversed_dict = {v: k for k, v in original.items()}  # {1: 'a', 2: 'b'}

# 集合推导式:去重并转换
unique_squares = {x**2 for x in [1, 2, 2, 3]}  # {1, 4, 9}

✅ 列表推导式是这类语法的"原型",掌握它就掌握了整个家族!


九、最佳实践总结

场景 推荐做法
简单映射/过滤 用列表推导式
多层嵌套(>2) 改用普通循环
需要副作用 for 循环
内存敏感 用生成器表达式 (x for x in ...)
构建字典/集合 用对应推导式 {}
性能关键路径 优先推导式(比 map/filter 更快更清晰)

🌈 Python 之禅提醒我们
"可读性很重要。"

当推导式变得难以一眼看懂,就是该停手的时候。


十、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
蓝色汪洋2 小时前
luogu填坑
开发语言·c++·算法
毕设源码-朱学姐2 小时前
【开题答辩全过程】以 基于PHP的高校心理测评系统的设计与实现为例,包含答辩的问题和答案
开发语言·php
2501_921649492 小时前
外汇与贵金属行情 API 集成指南:WebSocket 与 REST 调用实践
网络·后端·python·websocket·网络协议·金融
落雪snowflake2 小时前
compute_entropy函数
pytorch·python·深度学习
shenzhenNBA2 小时前
python用openpyxl操作excel-读取或创建excel文件
python·excel·读取excel·创建excel文件
小霖家的混江龙2 小时前
大模型如何分辨 “狼” 和 “狗” —— 词向量的训练过程
人工智能·python·llm
while(1){yan}2 小时前
网络编程UDP
java·开发语言·网络·网络协议·青少年编程·udp·电脑常识
大猫子的技术日记2 小时前
【工具篇】极简入门 UV Python项目管理工具
开发语言·python·uv
程序媛徐师姐2 小时前
Python基于Flask的mooc课程情感分类系统【附源码、文档说明】
python·flask·python慕课课程情感分类·mooc课程情感分类系统·慕课课程情感分类系统·python课程情感分类系统·python课程情感分类