当前位置: 首页 > news >正文

Python列表推导式完全指南

从循环到一行代码:Python列表推导式完全指南

在Python中,列表推导式(List Comprehension)是一种简洁、高效的创建列表的语法。它能将原本需要多行循环+条件判断的代码,浓缩成一行可读性强的表达式。但对新手来说,这种“一行代码”可能显得晦涩——本文通过10+实例,从基础到进阶,带你彻底掌握列表推导式的用法。

一、什么是列表推导式?先看一个直观对比

假设我们需要创建一个包含1-10整数的列表,用普通for循环的写法是:

# 普通for循环创建列表
numbers = []
for i in range(1, 11):numbers.append(i)
print(numbers)  # 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

而用列表推导式,只需一行代码:

# 列表推导式创建同样的列表
numbers = [i for i in range(1, 11)]
print(numbers)  # 输出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

核心语法[表达式 for 变量 in 可迭代对象]

  • 可迭代对象:可以是列表、range、字符串、字典等任何可循环的对象(如range(1,11)[1,2,3]);
  • 变量:每次循环从可迭代对象中取出的元素(如i);
  • 表达式:对变量的处理(可以是变量本身,也可以是运算、函数调用等,如i*2str(i))。

二、基础用法:用推导式简化“循环+添加”逻辑

列表推导式的核心价值是简化“遍历→处理→收集”的流程。以下是几个基础场景:

1. 对元素做简单运算

比如将1-5的每个数翻倍:

# 普通循环
doubles = []
for i in range(1, 6):doubles.append(i * 2)# 列表推导式
doubles = [i * 2 for i in range(1, 6)]
print(doubles)  # 输出:[2, 4, 6, 8, 10]

2. 转换元素类型

比如将列表中的整数转为字符串:

# 普通循环
str_numbers = []
for num in [1, 2, 3, 4]:str_numbers.append(str(num))# 列表推导式
str_numbers = [str(num) for num in [1, 2, 3, 4]]
print(str_numbers)  # 输出:['1', '2', '3', '4']

3. 遍历字符串生成字符列表

比如将字符串“hello”拆成单个字符的列表:

# 普通循环
chars = []
for c in "hello":chars.append(c)# 列表推导式
chars = [c for c in "hello"]
print(chars)  # 输出:['h', 'e', 'l', 'l', 'o']

三、进阶用法:带条件的列表推导式

列表推导式可以加入if条件,实现“筛选元素”的功能。语法分为两种:单条件筛选条件分支处理

1. 单条件筛选:保留符合条件的元素

比如从1-10中筛选出偶数:

# 普通循环
evens = []
for i in range(1, 11):if i % 2 == 0:  # 只保留偶数evens.append(i)# 列表推导式:[表达式 for 变量 in 可迭代对象 if 条件]
evens = [i for i in range(1, 11) if i % 2 == 0]
print(evens)  # 输出:[2, 4, 6, 8, 10]

再比如从混合列表中筛选出字符串:

mixed = [1, "apple", 3.14, "banana", True]
# 筛选出类型为字符串的元素
strings = [x for x in mixed if isinstance(x, str)]
print(strings)  # 输出:['apple', 'banana']

2. 条件分支:不同条件做不同处理

如果需要对“符合条件”和“不符合条件”的元素分别处理,可以用if-else分支。语法:[表达式1 if 条件 else 表达式2 for 变量 in 可迭代对象]

比如将1-10中的偶数保持不变,奇数转为0:

# 普通循环
result = []
for i in range(1, 11):if i % 2 == 0:result.append(i)  # 偶数保留else:result.append(0)  # 奇数转0# 列表推导式
result = [i if i % 2 == 0 else 0 for i in range(1, 11)]
print(result)  # 输出:[0, 2, 0, 4, 0, 6, 0, 8, 0, 10]

再比如给列表中的正数加1,负数减1,0保持不变:

nums = [3, -2, 0, 5, -1]
processed = [n+1 if n > 0 else n-1 if n < 0 else 0 for n in nums]
print(processed)  # 输出:[4, -3, 0, 6, -2]

四、高级用法:嵌套列表推导式

当需要处理嵌套结构(如二维列表)时,列表推导式可以嵌套使用,替代多层for循环。

1. 展平二维列表

比如将[[1,2], [3,4], [5,6]]展平为[1,2,3,4,5,6]

# 普通循环(两层for)
flat = []
for sublist in [[1,2], [3,4], [5,6]]:for num in sublist:flat.append(num)# 嵌套列表推导式:[表达式 for 外层变量 in 外层可迭代对象 for 内层变量 in 内层可迭代对象]
flat = [num for sublist in [[1,2], [3,4], [5,6]] for num in sublist]
print(flat)  # 输出:[1, 2, 3, 4, 5, 6]

2. 创建二维列表(矩阵)

比如创建一个3x3的乘法表(行索引×列索引):

# 普通循环(两层for)
multi_table = []
for i in range(1, 4):  # 行索引1-3row = []for j in range(1, 4):  # 列索引1-3row.append(i * j)multi_table.append(row)# 嵌套列表推导式
multi_table = [[i*j for j in range(1,4)] for i in range(1,4)]
print(multi_table)
# 输出:[[1, 2, 3], [2, 4, 6], [3, 6, 9]]

注意:外层推导式控制“行”,内层推导式控制“每行的元素”,逻辑和嵌套for循环完全对应。

3. 带条件的嵌套推导式

比如从二维列表中筛选出大于5的元素:

matrix = [[1, 6, 3],[8, 2, 5],[4, 9, 0]
]
# 筛选出所有>5的元素
filtered = [num for row in matrix for num in row if num > 5]
print(filtered)  # 输出:[6, 8, 9]

五、列表推导式 vs 其他方法:为什么选它?

列表推导式不是唯一创建列表的方法,和mapfilter等函数相比,它的优势在于可读性灵活性

1. 与map对比:处理元素转换

map函数也能实现元素转换,但语法不如推导式直观:

# 用map将1-5转为字符串
map_result = list(map(str, range(1,6)))
# 用列表推导式
lc_result = [str(i) for i in range(1,6)]
print(map_result == lc_result)  # 输出:True(结果相同)

当转换逻辑复杂时(比如带条件),推导式更清晰:

# 复杂转换:偶数转字符串,奇数保持整数
# 用map需要嵌套lambda,可读性差
map_result = list(map(lambda x: str(x) if x%2==0 else x, range(1,6)))
# 用列表推导式,逻辑一目了然
lc_result = [str(x) if x%2==0 else x for x in range(1,6)]
print(lc_result)  # 输出:[1, '2', 3, '4', 5]

2. 与filter对比:筛选元素

filter函数用于筛选元素,但同样不如推导式灵活:

# 筛选1-10中的偶数
# 用filter
filter_result = list(filter(lambda x: x%2==0, range(1,11)))
# 用列表推导式
lc_result = [x for x in range(1,11) if x%2==0]
print(filter_result == lc_result)  # 输出:True(结果相同)

如果筛选后还需要处理元素(比如偶数翻倍),推导式可以一步完成,而filter+map需要嵌套:

# 偶数翻倍,奇数不保留
# 用filter+map,需要两次函数调用
fm_result = list(map(lambda x: x*2, filter(lambda x: x%2==0, range(1,11))))
# 用列表推导式,一次完成
lc_result = [x*2 for x in range(1,11) if x%2==0]
print(lc_result)  # 输出:[4, 8, 12, 16, 20]

六、使用列表推导式的注意事项

列表推导式虽好,但过度使用会适得其反:

1. 避免过度嵌套,保持可读性

三层及以上的嵌套推导式会变得晦涩,比如:

# 不推荐:三层嵌套,可读性差
nested = [[[i+j+k for k in range(2)] for j in range(2)] for i in range(2)]
# 推荐:用普通循环+注释,逻辑更清晰
nested = []
for i in range(2):layer2 = []for j in range(2):layer3 = []for k in range(2):layer3.append(i+j+k)layer2.append(layer3)nested.append(layer2)

2. 大数据场景慎用:列表推导式会一次性生成全部元素

如果需要处理百万级以上的数据,列表推导式会瞬间占用大量内存(因为它会创建完整列表)。此时应使用生成器表达式(将[]改为()),按需生成元素:

# 列表推导式:一次性生成100万个元素,占用大量内存
big_list = [i for i in range(1000000)]# 生成器表达式:按需生成,内存友好
big_generator = (i for i in range(1000000))  # 不占内存

3. 复杂逻辑优先用函数封装

如果推导式中的“表达式”或“条件”过于复杂(比如多行逻辑),应拆分成函数,再在推导式中调用:

# 复杂逻辑:判断一个数是否为质数(简化版)
def is_prime(n):if n < 2:return Falsefor i in range(2, int(n**0.5)+1):if n % i == 0:return Falsereturn True# 用推导式筛选1-100中的质数(逻辑清晰)
primes = [n for n in range(1, 101) if is_prime(n)]

七、总结:列表推导式的核心价值

列表推导式是Python“简洁优雅”哲学的典型体现,它的核心优势是:

  1. 简洁:将多行循环+条件的代码浓缩为一行;
  2. 高效:比普通for循环执行速度更快(底层优化);
  3. 可读:在合理复杂度下,比map/filter更符合人类阅读习惯。

记住:列表推导式的本质是“循环+处理+收集”的语法糖。遇到创建列表的场景时,先想想:“这个逻辑能用推导式简化吗?”——但永远以“可读性”为前提,不要为了“一行代码”而牺牲清晰度。

从现在开始,试着把代码中的for+append改成推导式吧,你会慢慢爱上这种“一行搞定”的快感~

http://www.jsqmd.com/news/30400/

相关文章:

  • Rockchip RK3588 - Mali-G610 GPU驱动(mesa+Panthor)
  • AI浪潮下的学习与就业:机遇还是陷阱?
  • win10安装MongoDB 3.0.15 Community
  • auto
  • 一行“优雅”代码踩爆3x3矩阵:Python列表乘法的“共享引用”陷阱
  • 写给创业者新手:什么是MAU指标,什么是ARR、PMF
  • git不小心把本地从未提交过的贮藏的版本删掉了,如何恢复?
  • ffmpeg安装配置
  • 【C】 static用法
  • Python线程锁
  • 若依前端验证码的实现
  • 从O(n)到O(n):Python字符串拼接的效率陷阱与最佳实践
  • 实验4:MobileNet ShuffleNet - OUC
  • 模拟赛 31
  • CSP-S 2025 T3 小结
  • 第三十二篇
  • 2025年苏州AIGEO 优化服务商深度测评:TOP5 企业核心优势与实战案例对比
  • 使用 Docker Compose 轻松实现 INFINI Console 离线部署与持久化管理
  • 第6章 语句
  • 十一月杂题
  • Modbus RTU 通信格式详解学习笔记
  • Selenium3+Python3 自动化项目项目实战day1
  • P1.python环境的配置和安装
  • Python 中可变对象的“引用赋值”特性——可变对象的“引用传递”
  • CSP-S 2025 游寄喵
  • Modbus协议分类及测试学习笔记
  • MarkDown初入
  • 英语_作文_8AU3_Curiosity
  • 习题-极大原理
  • 极大原理