news 2026/6/3 16:49:16

Python列表推导式:一行代码搞定复杂循环

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python列表推导式:一行代码搞定复杂循环

Python列表推导式:一行代码搞定复杂循环

一、导语

刚学Python时,你是不是也写过这样的代码——先创建一个空列表,然后写一个for循环,再一行一行往里面append数据?这段代码通常要占四五行,每次写都觉得很啰嗦。其实Python早就为我们准备了一个优雅的替代方案:列表推导式(List Comprehension)

列表推导式是Python最受欢迎的特性之一。它可以把多行的循环+条件逻辑压缩成一行,代码不仅更短,读起来也更接近"人类语言"。本文带你从入门到进阶,彻底掌握这个利器。

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

先看一个最简单的场景:生成1到10的平方数列表。

传统写法(3行):

squares=[]foriinrange(1,11):squares.append(i**2)print(squares)# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

列表推导式(1行):

squares=[i**2foriinrange(1,11)]print(squares)# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

语法拆解一下:[表达式 for 变量 in 可迭代对象]

  • for i in range(1, 11)— 和普通循环的for一样,依次取出每个元素
  • i ** 2— 对每个元素执行的表达式,结果直接放入新列表
  • 外面用[]包起来,表示我们要的是一个列表

把这个结构记牢,后面所有变体都是在这个基础上的扩展。

三、加上条件过滤:if的妙用

现实场景中,我们经常需要筛选数据。比如从一堆数字里挑出偶数再求平方。

传统写法:

even_squares=[]foriinrange(1,21):ifi%2==0:even_squares.append(i**2)

列表推导式:

even_squares=[i**2foriinrange(1,21)ifi%2==0]print(even_squares)# [4, 16, 36, 64, 100, 144, 196, 256, 324, 400]

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

注意if写在for后面,而不是表达式前面。这恰好符合我们阅读的顺序——“从1到20里取出i,如果i是偶数,就计算i的平方”。

四、if-else:条件表达式放前面

如果筛选还不够,需要对不同情况做不同处理,就用if-else。但要记住一个重要区别:if-else写在表达式位置,if(无else)写在循环后面

# 偶数求平方,奇数保持不变result=[i**2ifi%2==0elseiforiinrange(1,11)]print(result)# [1, 4, 3, 16, 5, 36, 7, 64, 9, 100]

结构是:[结果A if 条件 else 结果B for i in ...]。这是Python的三元表达式嵌入到了推导式中。

对比记忆法:

场景写法位置
只要符合条件的if 条件for后面
符合条件的做A,否则做BA if 条件 else Bfor前面(表达式位置)

五、嵌套循环:多维数据的处理利器

遇到二维列表(矩阵)时,列表推导式同样能大显身手。

展平二维列表:

matrix=[[1,2,3],[4,5,6],[7,8,9]]# 传统写法flat=[]forrowinmatrix:fornuminrow:flat.append(num)# 推导式:for的顺序和传统嵌套一致flat=[numforrowinmatrixfornuminrow]print(flat)# [1, 2, 3, 4, 5, 6, 7, 8, 9]

注意for的书写顺序:外层循环在前,内层循环在后,这和普通嵌套循环的书写顺序完全一致,非常好记。

再加条件过滤:

# 只提取大于5的元素flat_big=[numforrowinmatrixfornuminrowifnum>5]print(flat_big)# [6, 7, 8, 9]

六、实战场景:五个工作中常用的例子

6.1 清洗字符串列表

names=[" Alice ","BOB"," Charlie ","david"]clean=[name.strip().title()fornameinnames]print(clean)# ['Alice', 'Bob', 'Charlie', 'David']

6.2 筛选有效邮箱

emails=["alice@qq.com","invalid","bob@163.com","not-an-email","charlie@gmail.com"]valid=[eforeinemailsif"@"ineand"."ine.split("@")[-1]]print(valid)# ['alice@qq.com', 'bob@163.com', 'charlie@gmail.com']

6.3 字典列表提取字段

users=[{"name":"张三","age":28,"city":"北京"},{"name":"李四","age":35,"city":"上海"},{"name":"王五","age":22,"city":"深圳"},]names=[u["name"]foruinusers]print(names)# ['张三', '李四', '王五']# 30岁以上用户的城市cities=[u["city"]foruinusersifu["age"]>30]print(cities)# ['上海']

6.4 文件路径批量处理

importos# 获取当前目录下所有.py文件的绝对路径py_files=[os.path.abspath(f)forfinos.listdir(".")iff.endswith(".py")]

6.5 生成笛卡尔积

colors=["红","蓝","绿"]sizes=["S","M","L"]combinations=[f"{c}-{s}"forcincolorsforsinsizes]print(combinations)# ['红-S', '红-M', '红-L', '蓝-S', '蓝-M', '蓝-L', '绿-S', '绿-M', '绿-L']

七、不止列表:字典推导式与集合推导式

学会了列表推导式,另外两种推导式就是换一对括号的事。

字典推导式:

# 把列表转成字典:名字→长度words=["python","java","golang"]word_len={w:len(w)forwinwords}print(word_len)# {'python': 6, 'java': 4, 'golang': 6}# 键值互换d={"a":1,"b":2,"c":3}reversed_d={v:kfork,vind.items()}print(reversed_d)# {1: 'a', 2: 'b', 3: 'c'}

集合推导式:

# 获取字符串中所有不重复的字母text="hello world"unique_chars={cforcintextifc!=" "}print(unique_chars)# {'d', 'e', 'h', 'l', 'o', 'r', 'w'}

八、注意事项:推导式不是万能药

列表推导式虽好,但过度使用会让代码变得难以阅读:

# 反面教材:嵌套三层还带条件,读起来很痛苦result=[x*yforxinrange(10)ifx%2==0foryinrange(10)ify%3==0]

使用原则:

  • 两层嵌套是上限:超过两层,老老实实用传统for循环
  • 单个推导式不超过一行:如果一行写不完(超过约80字符),拆成多行或用普通循环
  • 复杂逻辑拆出来:如果表达式本身就很复杂,先定义成函数,再在推导式中调用
# 拆成函数,推导式就清晰了defnormalize(s):returns.strip().lower().replace("-","_")fields=[" User-Name ","Email-Address "," Phone-Number"]result=[normalize(f)forfinfields]print(result)# ['user_name', 'email_address', 'phone_number']

九、总结

列表推导式是Python中"少即是多"哲学的典型体现。核心要点回顾:

要素说明
基本语法[表达式 for 变量 in 可迭代对象]
条件筛选[表达式 for 变量 in 可迭代对象 if 条件]
条件分支[A if 条件 else B for 变量 in 可迭代对象]
嵌套循环[表达式 for 外层 in 容器1 for 内层 in 容器2]
字典推导{键: 值 for ... in ...}
集合推导{元素 for ... in ...}

掌握了列表推导式,你会发现很多原本需要五六行的循环逻辑,一行就能优雅地解决。代码更简洁,也更Pythonic。下次写循环前,不妨先想想:能不能用推导式搞定?


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/3 16:48:28

Jina Reader终极指南:3步让AI读懂整个互联网的免费方案

Jina Reader终极指南:3步让AI读懂整个互联网的免费方案 【免费下载链接】reader Convert any URL to an LLM-friendly input with a simple prefix https://r.jina.ai/ 项目地址: https://gitcode.com/GitHub_Trending/rea/reader 你是否曾为AI应用无法实时获…

作者头像 李华
网站建设 2026/6/3 16:48:23

macOS原生运行的Code::Blocks IDE安装包(标准.app格式,开箱即用)

本文还有配套的精品资源,点击获取 简介:专为Mac用户准备的Code::Blocks集成开发环境,打包成符合苹果规范的CodeBlocks.app应用,结构完整:包含Contents目录、Info.plist配置文件、MacOS子目录下的可执行二进制文件&a…

作者头像 李华
网站建设 2026/6/3 16:46:57

条码生成的革命性方案:Libre Barcode让专业条码像打字一样简单

条码生成的革命性方案:Libre Barcode让专业条码像打字一样简单 【免费下载链接】librebarcode Libre Barcode: barcode fonts for various barcode standards. 项目地址: https://gitcode.com/gh_mirrors/li/librebarcode 还在为复杂的条码生成软件而烦恼吗&…

作者头像 李华
网站建设 2026/6/3 16:46:08

Arduino渐进式夏令时时钟:非阻塞算法与时间平滑过渡实践

1. 项目概述与设计初衷作为一名长期混迹于创客社区和嵌入式开发领域的爱好者,我经手过不少时钟项目,从最基础的DS1302 RTC模块到网络授时的NTP时钟。但这次,我想做点不一样的。传统的数字时钟,无论是依靠单片机内部时钟还是外置RT…

作者头像 李华