尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Effective Python 条款 7:告别range下标,善用enumerate与zip写出清爽代码

Effective Python 条款 7:告别range下标,善用enumerate与zip写出清爽代码 Effective Python 条款 7告别range下标善用enumerate与zip写出清爽代码Bilibili 同步视频别再用 range 下标遍历序列enumerate优雅获取循环序号的神器简单小案例统计二进制位写在后面即将登场的 zip 并行遍历✨最佳实践速记写 Python 最怕什么满屏的下标、生硬的range(len(list))循环代码绕来绕去读起来费脑子改起来容易踩坑。很多新手刚上手时习惯用其他语言的思维写循环写出一堆不够 Pythonic 的代码。今天我们就聊聊迭代场景下两个宝藏内置函数enumerate和zip帮你把循环写得简洁又优雅✨。Bilibili 同步视频Effective Python 条款 7告别range下标善用enumerate与zip写出清爽代码别再用 range 下标遍历序列很多刚从 C/C 转 Python 的开发者遍历列表需要获取元素位置时第一反应会写出下面这种代码flavor_list[vanilla,chocolate,pecan,strawberry]# 不推荐的写法foriinrange(len(flavor_list)):flavorflavor_list[i]print(f{i1}:{flavor})这段代码逻辑没问题可以正常输出口味和对应的排名。但它有几个很明显的短板先要调用len()获取列表长度再用range生成下标数字步骤繁琐循环拿到下标之后还要再通过下标去取列表元素多了一层索引访问代码阅读成本高一眼看过去分不清i到底代表什么后续维护很容易因为下标偏移出现 bug。Python 的哲学直接迭代容器本身而不是迭代下标数字。如果我们只需要元素完全不需要下标直接遍历列表就足够了flavor_list[vanilla,chocolate,pecan,strawberry]forflavorinflavor_list:print(f{flavor}is delicious)这种写法干净利落不需要维护索引变量可读性直接拉满。但现实开发里我们经常既要拿到元素又要拿到它的序号这时候该怎么办enumerate优雅获取循环序号的神器Python 内置enumerate就是专门解决这个痛点的工具。enumerate会接收一个迭代器把它包装成一个惰性生成器。每次迭代的时候会同时返回序号 当前元素这一组数据配合 Python 的解包语法一行 for 循环就能搞定两件事。我们可以手动调用next()直观感受它的内部输出flavor_list[vanilla,chocolate,pecan,strawberry]itenumerate(flavor_list)print(next(it))print(next(it))输出(0, vanilla) (1, chocolate)可以看到每一轮返回的是元组第一个值是索引第二个是列表元素。利用解包直接写到 for 循环变量中flavor_list[vanilla,chocolate,pecan,strawberry]fori,flavorinenumerate(flavor_list):print(f{i1}:{flavor})默认序号是从 0 开始所以我们需要手动i1做排名。但是enumerate还藏了一个超好用的第二参数可以直接指定起始编号不用循环内部做数字偏移flavor_list[vanilla,chocolate,pecan,strawberry]# 第二个参数设置起始序号直接从1开始计数fori,flavorinenumerate(flavor_list,1):print(f{i}:{flavor})输出结果1: vanilla 2: chocolate 3: pecan 4: strawberry✅enumerate核心要点总结它封装迭代器惰性产出 (序号元素)不会一次性把全部数据加载内存优先替代range(len(xxx))这种下标遍历写法第二个入参可以自定义起始序号默认值为 0配合解包语法代码清爽阅读者一眼看懂变量含义。小补充对比性能enumerate和range下标总体性能差距很小它的核心收益不是跑的更快而是降低代码出错概率提升可读性。写业务代码可读性往往比几纳秒的性能更重要。简单小案例统计二进制位再看一个小例子用 range 遍历整数序列是合适的因为我们本身就是要操作数字本身fromrandomimportrandint random_bits0foriinrange(32):ifrandint(0,1):random_bits|1iprint(bin(random_bits))划重点range适合迭代数字本身而遍历容器、列表、字符串这类序列需要序号优先选enumerate不要强行用 range 做下标。写在后面即将登场的 zip 并行遍历实际开发中除了单列表带序号遍历我们还经常遇到需要同时遍历两个甚至多个列表的场景比如源列表生成派生列表一一对应处理两组数据。这时候就轮到zip出场它可以把多个迭代器打包在一起同步迭代避免手动维护下标去对齐两组数据同样可以规避大量下标相关的 bug。✨最佳实践速记场景推荐写法不推荐写法只取元素不需要序号for item in listfor i in range(len(list))需要元素 序号for i,item in enumerate(list, start1)for i in range(len(list)): item list[i]需要单纯生成数字序列range(n)不要强行构造列表来生成数字Pythonic 的代码本质就是少写手动下标、多用语言内置工具和解包让代码表达业务逻辑而不是表达循环索引的细节。把繁琐的索引管理交给语言内置函数我们专注业务逻辑本身。小结迭代序列优先直接遍历对象不要无脑用 range 生成下标访问需要序号时优先使用enumerate支持自定义起始序号range适合的场景是迭代数字而不是用来拿容器下标善用解包语法让循环变量语义清晰降低后续维护成本。后续我们继续拆解zip的用法聊聊并行遍历多个迭代器的坑与技巧。
返回列表