☰
Python循环全攻略:for/while、迭代器与避坑技巧
2026/10/11 5:00:23 网站建设 项目流程

Python里的循环,说多不多,说少不少,但每次带新人或者自己回看老代码,总能发现一些值得唠叨的细节。这份整理我是按“极简但不简单”的方式做的,目的不是把文档抄一遍,而是把 for 和 while 两条主线、break/continue/else 这类控制语句、迭代器协议、列表推导式,以及我在实际项目里踩过的几个坑,一次性讲明白。你如果刚接触 Python,可以把它当成查漏补缺的索引;如果你已经写了几年 Python,那重点看看后面的坑位和排错思路,说不定能帮你省下一个下午。

1. 循环的两条主线:for 和 while

1.1 for 循环的本质:遍历可迭代对象

很多从 C 语言转过来的人,刚用 Python 的 for 循环时会不习惯,因为在 C 里 for 是一个带初始条件、终止条件和步长的“计数器循环”,而 Python 的 for 是彻头彻尾的“迭代循环”——它的核心不是数数字,而是把一个可迭代对象里的元素挨个取出来。

for i in range(10): print(i)

这段代码里的range(10)并不是一个列表,而是一个 range 对象。Python 看到 for 时,会先对range(10)调用iter(),得到一个迭代器,然后不断调用next()拿到下一个值,直到抛出的异常是StopIteration才停止。换句话说,它和下面这种手动写法在原理上是一样的:

it = iter([1, 2, 3, 4, 5]) while True: try: value = next(it) print(value) except StopIteration: break

只是 for 帮你把这些细节全包了。这也是为什么 Python 的 for 能遍历字符串、列表、元组、字典、集合、文件对象、生成器等等几乎所有内置类型。你在 for 里写的那个变量,比如上面的i,只是每次从迭代器里取出来的“当前值”的引用,循环结束后它仍然存在,并且保留最后一次取值。

实际使用中有几个高频场景值得注意。遍历字典时,默认遍历的是 key:

person = {"name": "张三", "age": 18, "city": "北京"} for key in person: print(key)

如果想同时拿到 key 和 value,我会用.items():

for key, value in person.items(): print(key, value)

遍历字符串时,拿到的每个字符,包括空格和标点:

for ch in "Python": print(ch)

另外,很多人好奇为什么 Python 没有 C 风格的for (i = 0; i < 10; i++)。因为这种用法可以被range完整覆盖,而且 Python 的设计哲学是“统一序列操作接口”。你不需要记数组长度,不需要手动下标递增,只要对象是可迭代的,for 就能安全遍历完。这对代码的可读性提升不是一点点。

还有一个容易忽略的点:range本身是惰性求值的,它不会一次性生成 1 亿个数放在内存里。所以你写for i in range(100000000)时,内存占用很小。但如果你写list(range(100000000)),那才是真的把列表展开,内存立刻爆炸。记住这个区别,在数据量大的场景里很关键。

1.2 while 循环:条件才是主角

while 循环的结构更接近传统语言,它只判断一个条件表达式是否为真,为真就继续执行,为假就退出。常见格式:

count = 0 while count < 5: print(count) count += 1

这里最容易犯的错误就是忘记在循环体里更新count,一旦忘了,条件永远为真,程序就死循环了。我在调试别人的代码时,看到 while 循环第一眼永远是找“条件变量在哪里被修改”,找不到就怀疑是不是死循环。

while 的最佳使用场景是“循环次数不确定,但退出条件明确”。比如从用户输入里反复读取命令,直到用户输入quit:

command = "" while command != "quit": command = input("请输入命令(输入 quit 退出):")

再比如轮询某个任务状态、等待某个文件出现、重试网络请求直到成功。这种场景用 for 写会很别扭,因为你不知道总共要循环多少次,只有 while 能很自然地表达“只要条件满足,就一直跑”。

不过要注意,while 循环如果条件写得太宽泛,很容易跑飞。我比较喜欢在 while 里加一个最大重试次数限制,避免程序真正进入无限循环。例如:

retry = 0 max_retry = 3 while retry < max_retry: # 模拟尝试操作 success = False if success: break retry += 1 else: print("重试次数用完,仍然失败")

这里顺便用到了后面的 else 分支,先不展开。整体来说,while 适合表达“直到某件事发生”,for 适合表达“遍历这个集合里的一切”。拿到需求先问自己一句:我关心的是元素,还是退出条件?答案会决定你用哪个。

2. 循环控制:break、continue、else

2.1 break 和 continue 的正确用法

break 的作用是立即结束整个循环,continue 则是跳过本次循环的剩余部分,直接进入下一次迭代。这两个词看起来简单,但放的位置和边界条件很讲究。

看一个经典的例子:找 1 到 20 之间第一个能被 7 整除的数。

for i in range(1, 21): if i % 7 == 0: print("找到了:", i) break

没有 break 的话,循环会把所有 1 到 20 都遍历完。加了 break,一旦找到就立刻跳出,程序更高效,语义也更清晰。

再看 continue 的场景:打印 1 到 10 之间的所有偶数。

for i in range(1, 11): if i % 2 != 0: continue print(i)

当i是奇数时,continue 会让程序跳过下面的print(i),直接进入下一次循环,所以最后只打印偶数。continue 在你需要过滤某些条件时特别好用,它能让循环体保持平铺直叙,不用把所有逻辑都塞进一个大 if 里。

但注意别滥用。嵌套好几层循环的时候,break 只能跳出它所在的那一层,并不能跳出外层。很多人在这里犯迷糊。如果想跳出多层循环,更干净的做法是设置一个标志变量,或者把多层逻辑抽成函数后用 return 返回。

found = False for i in range(10): for j in range(10): if i * j == 42: found = True break if found: break

这种写法可读性还行,但如果你不想要标志变量,也可以把两层循环的逻辑封装到一个函数里,直接 return。我自己更倾向于函数化,因为 return 的意图比标志变量更明确。

2.2 容易被忽略的 else 分支

Python 的 for 和 while 后面可以跟一个 else,这个 else 会在循环“自然结束”时执行,也就是没有被 break 打断时执行。这个设计很多从其他语言过来的人会觉得反直觉,但用好了确实很舒服。

最经典的应用是判断素数:

num = 29 for i in range(2, num): if num % i == 0: print(num, "不是素数") break else: print(num, "是素数")

这里如果循环过程中num % i == 0,就会 break,else 块不会执行;如果遍历完都没有找到因子,循环正常结束,else 块执行,输出“是素数”。这个写法的好处是省掉了一个is_prime = True的中间变量,代码更短,语义也更贴合“如果没有被提前打断,就说明是素数”。

while 的 else 同理。比如轮询重试时,如果重试次数用完了还没有成功,就走 else 提示失败:

attempt = 0 while attempt < 3: # 模拟请求 success = False if success: break attempt += 1 else: print("三次都没成功")

不过我得提醒一句:for-else 和 while-else 的语义在团队协作中经常被误解,很多人不知道这个特性。如果你在团队项目里使用,最好在旁边加一行注释“循环没有被 break 才会来到这”。不然同事 review 时可能会一脸问号。

3. 循环背后的迭代协议

3.1 可迭代对象、迭代器和迭代器协议

要说循环,绕不开迭代器协议。Python 里只要对象实现了__iter__()方法返回迭代器,或者实现了__getitem__()方法支持按索引取值,它就是可迭代对象。迭代器本身还需要实现__next__(),每次返回下一个元素,没有元素时抛出StopIteration。

我经常用一个生活化类比来解释:可迭代对象像一本翻页日历,迭代器像日历的书签,书签每次往后挪一页,翻到最后一页再往后翻,就会提示“没有下一页了”,这个提示就是StopIteration。for 循环就是帮你反复做“翻页”这个动作,并在看到“没有下一页”时自动合上书。

如果你想更底层地感受循环,可以自己写一个简单的迭代器:

class CountDown: def __init__(self, start): self.count = start def __iter__(self): return self def __next__(self): if self.count <= 0: raise StopIteration self.count -= 1 return self.count + 1 for num in CountDown(5): print(num)

这段代码会打印 5、4、3、2、1。关键是__next__里要自己判断什么时候结束并抛出StopIteration。这个“手动感”能帮你理解 for 循环内部到底做了什么。

很多内置对象是迭代器,但有些是序列。字符串、列表、元组是可迭代的序列,但它们本身不是迭代器。迭代器是一次性的,遍历完就“耗尽”了。比如用iter()包一下列表:

a = [1, 2, 3] it = iter(a) print(next(it)) # 1 print(next(it)) # 2 print(next(it)) # 3 print(next(it)) # StopIteration

一旦耗尽,再 for 循环它就没有输出了。所以如果你想多次遍历同一个迭代器,得再重新生成一个。这个坑在把迭代器当作列表使用时特别容易踩,后面章节会再提到。

3.2 让循环更好用的内置函数

Python 提供了一些内置工具函数,它们本身并不神秘,但放在循环里能极大提升效率。

第一个是enumerate。它可以在遍历时同时得到索引和元素,省去手动维护一个index = 0再index += 1的麻烦:

fruits = ["苹果", "香蕉", "橙子"] for index, fruit in enumerate(fruits, start=1): print(index, fruit)

start=1可以让人工序号从 1 开始,这在输出报表时很常用。

第二个是zip。它能把多个可迭代对象按位置一一对应组合:

names = ["张三", "李四", "王五"] scores = [88, 92, 75] for name, score in zip(names, scores): print(name, score)

输出类似“张三 88”这样的组合。zip 在同时迭代两个列表时比用下标取names[i]和scores[i]要优雅得多,而且当两个列表长度不一致时,zip 会以较短的那个为准,避免越界报错。

第三个是reversed。它可以反向遍历序列:

for i in reversed(range(10)): print(i)

注意reversed返回的是一个反向迭代器,不是列表,所以如果你要真正的列表,用list(reversed(range(10)))包一下。

第四个是sorted。虽然它返回的是列表,但你可以直接for i in sorted(set_a)遍历排序后的结果。需要注意sorted默认会新建列表并排序,不会修改原对象,而列表的.sort()方法会原地排序。

这些工具函数的共同点是让循环的“意图”更清晰,减少你在循环体内手工算下标的工作量。我一般看到别人写:

for i in range(len(lst)): print(i, lst[i])

都会建议改成enumerate版本,因为后者明确表达了“我需要索引的同时也需要元素”。

3.3 生成器:让循环里的数据流变得轻量

生成器可以理解为一种特殊的迭代器,它用yield关键字产出值,每次 for 循环在取下一个值时,生成器函数会在上次停止的地方继续执行,直到函数结束或遇到return。

最简单的生成器函数:

def my_range(n): i = 0 while i < n: yield i i += 1 for i in my_range(5): print(i)

如果你手动调next(),能看到它是一步一步“挤牙膏”地把值吐出来的。这种惰性求值方式在处理大数据时非常有用。比如你要读取一个 10 GB 的文件,如果直接data = open("big.txt").read(),内存会撑不住;但用循环一行一行处理就完全没问题:

with open("big.txt", "r", encoding="utf-8") as f: for line in f: process(line)

这里文件对象本身就是惰性迭代器,每次循环只取一行。生成器和迭代器协议是 Python 处理流式数据的基石。

生成器表达式也值得提一句:用小括号写推导式,不立即生成全部值,而是生成一个生成器对象:

gen = (x * x for x in range(10000)) for value in gen: print(value)

它比列表推导式省内存,适合在数据量未知或很大的场景下使用。但缺点是不能反复遍历,只能迭代一次,所以用之前要想清楚数据流是一次性消费还是需要复用。

4. 写循环的进阶姿势:推导式与更精简的表达

4.1 列表推导式:一行顶五行的常见写法

列表推导式是 Python 里把循环和列表构建压缩成一行的语法糖,基本格式是:

[expression for item in iterable if condition]

例如,把 1 到 20 里的偶数平方收集到一个列表:

squares = [i * i for i in range(1, 21) if i % 2 == 0]

如果不用推导式,你得写:

squares = [] for i in range(1, 21): if i % 2 == 0: squares.append(i * i)

显然推导式更短,而且在高频操作里性能通常更好,因为它在底层用 C 优化的迭代循环,减少了方法查找和动态扩展的开销。

我建议你把它理解成一个“先写循环,再压缩表达式”的过程。当你面对一个数据转换任务时,先写完整版:

result = [] for item in list_a: if item > 0: result.append(item * 2)

然后再压缩成:

result = [item * 2 for item in list_a if item > 0]

熟练之后直接写推导式没问题。但不建议一上来就写特别复杂的链式推导式,比如同时嵌套多个 for 和 if,那样子可读性很差。代码是给人读的,不只是给机器跑的。

4.2 字典推导式与集合推导式

推导式不只属于列表。字典推导式用花括号,key 和 value 之间用冒号分隔:

squares_dict = {i: i * i for i in range(5)} # 结果:{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

集合推导式同样用花括号,但没有冒号:

nums = [1, 2, 2, 3, 3, 3, 4] unique_nums = {x for x in nums} # 结果:{1, 2, 3, 4}

用途很广。比如从一堆数据中提取字段构造字典,或者做去重统计,推导式都能派上用场。注意集合是一组无序且唯一的对象,所以输出顺序不保证,如果你需要有序去重,配合sorted()使用。

4.3 什么时候不该用列表推导式

列表推导式虽好,但有三类情况我倾向用普通 for 循环。

第一种是逻辑分支太复杂的时候。比如要同时对多个条件做不同变换,推导式会写成一长串表达式,肉眼很难追踪。第二种是需要修改外部变量或者有副作用的操作。推导式本质上是构建新列表,如果你在推导式里调用函数去改外部状态,那就很反直觉,也会让代码难调试。第三种是嵌套层次超过两层。正常的多重嵌套可以用推导式,但超过两层后,忽略缩进的视觉层次会让人看不明白。

举一个比较“痛苦”的例子:

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] flat = [num for row in matrix for num in row if num % 2 == 0]

这是一层嵌套,展开成普通 for 是这样:

flat = [] for row in matrix: for num in row: if num % 2 == 0: flat.append(num)

这种程度的嵌套还能接受。但如果再加一层,可读性就会明显下降。我通常的建议是:推导式让你觉得“有点绕”的时候,就拆回普通 for 循环。代码规范是给自己和同事看的,不是为了炫耀语法技巧。

5. 嵌套循环、性能陷阱与优化思路

5.1 嵌套循环的经典场景:矩阵与笛卡尔积

嵌套循环在数据处理里很常见。最典型的是遍历二维矩阵:

matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], ] for row in matrix: for cell in row: print(cell, end=" ") print()

这也对应着“每个元素都要访问一遍”的场景。再比如生成九九乘法表:

for i in range(1, 10): for j in range(1, i + 1): print(f"{j}x{i}={i*j}", end="\t") print()

嵌套循环本身不复杂,复杂的是性能。多重循环会让计算量指数级增长,所以优化思路一般集中在“减少循环层数”或者“减少内层循环的执行次数”。

5.2 用 itertools.product 替代多层嵌套

当你要枚举多个序列的笛卡尔积时,不要手工写三层 for,Python 的itertools模块里已经有现成的工具:

import itertools colors = ["红", "绿", "蓝"] sizes = ["S", "M", "L"] for color, size in itertools.product(colors, sizes): print(color, size)

这段代码等价于两层 for 嵌套。用product之后,代码更扁平,也更容易在后面增加更多维度,而不会导致缩进越来越深。

实际工作中,我遇到过一个需求:要从时间、地点、业务类型三个维度组合生成报表,最初实现是三层 for 嵌套,后面需求要加一个渠道维度,导致嵌套又深了一层,看起来非常臃肿。改成itertools.product后,无论多少维度,循环体都不用改,参数加一个列表就行,修改成本极低。

5.3 循环性能优化的小技巧

循环性能并不是玄学,很多时候只要减少无谓的重复计算,就能明显提速。我总结几个自己常用的点。

第一,把循环体内不会变化的值提到循环外。比如:

# 不推荐:len(lst) 每次循环都调用 for i in range(len(lst)): do_something(lst[i], len(lst)) # 推荐 n = len(lst) for i in range(n): do_something(lst[i], n)

虽然 Python 的len()很快,但原理上没必要重复计算。

第二,能用内置函数解决就别自己写循环。比如求和用sum(),统计数量用count(),排序用sorted(),去重用set()。内置函数是 C 实现的,性能远高于 Python 层的逐元素循环。

第三,查找成员用集合而不是列表。如果你需要在循环里反复判断某个元素是否在另一个容器中,用列表的in是 O(n),用集合的in是 O(1)。数据量一上来,差别非常明显。

# 慢:列表查找 allowed = [1, 2, 3, 4, 5] for x in big_list: if x in allowed: pass # 快:集合查找 allowed = {1, 2, 3, 4, 5} for x in big_list: if x in allowed: pass

第四,有限循环中尽量用局部变量缓存方法。比如在循环里反复调用list.append,可以先append = lst.append,再把append(x)放进循环。这个优化在老代码里很常见,虽然现代 Python 解释器已经优化了不少,但性能敏感场景仍然有效。

优化循环时别魔怔,先分析瓶颈在哪。大多数时候我们要先保证逻辑正确,再用timeit对这种细节做基准测试。如果循环体内是外部 IO 操作,那再快的 Python 循环也救不了网络延迟,这时候该考虑并发或批量请求。

6. 实战中容易踩的坑与排查技巧

6.1 循环遍历过程中修改列表:经典翻车现场

最经典的坑是边遍历边删除列表元素。看这个例子:

lst = [1, 2, 3, 4, 5] for item in lst: if item % 2 == 0: lst.remove(item) print(lst)

预期想删掉所有偶数,但结果却是[1, 3, 5]吗?不是,实际输出可能让你意外:[1, 3, 5]其实看着是对的,但为什么说它是坑?因为我们遍历时会跳过元素。试一个更明显的:

lst = [1, 2, 3, 4, 5] for item in lst: lst.remove(item) print(lst)

结果并不是空列表,而是[2, 4]。原因是 for 循环通过索引迭代:第一次取lst[0]是 1,删除它之后,列表变成[2,3,4,5],下一次循环取lst[1],此时取到的是原来的 3,原来的 2 被跳过了。这种问题很隐蔽,完全不会报错,但结果就是错的。

正确的做法有两个方向。如果只是读和改,不改列表长度,那没问题;如果要删除符合条件的元素,建议遍历副本:

lst = [1, 2, 3, 4, 5] for item in lst[:]: if item % 2 == 0: lst.remove(item) print(lst)

或者用推导式直接构建新列表:

lst = [item for item in lst if item % 2 != 0]

更推荐后者,filter 的意图更清晰,而且没有修改原列表时的副作用。如果你确实要原地修改,也可以倒序遍历:

lst = [1, 2, 3, 4, 5] for i in range(len(lst) - 1, -1, -1): if lst[i] % 2 == 0: del lst[i]

倒序遍历时删除元素不会影响前面元素的索引,比较安全。

6.2 对迭代器“一次性”的错误预期

另一个让我印象深刻的坑是把迭代器当成列表重复遍历。比如:

lines = (line.strip() for line in open("a.txt")) for line in lines: print(line) # 这里再想遍历一遍,发现什么也没有 for line in lines: print(line)

第二次循环不会有任何输出,因为生成器已经耗尽。如果你需要多次遍历,要么把数据存成列表,要么重新生成迭代器。这在处理文件对象时特别常见,很多人第一次用完文件对象后想再遍历一次,文件指针已经在末尾了,自然读不到内容。

一个相关场景是range对象。range 可以被反复迭代,因为它不是一次性迭代器,你每次 for 它都会生成一个全新的迭代器。所以想重复遍历时优先考虑用range、list这类支持多次迭代的对象,而不是生成器或单个迭代器。

6.3 while 循环变量忘了更新:死循环排查思路

while 死循环最常见的原因是循环体里没有更新条件变量。比如:

i = 0 while i < 10: print(i) # 忘记 i += 1

程序会一直打印 0。处理这种问题时,我会先检查循环体内有没有修改条件变量的语句,如果没有,基本可以断定是死循环。如果确认有修改,但程序还是卡住,我会在循环体开头打印条件变量,观察它是否在变化:

i = 0 while i < 10: print("debug i =", i) i += 1

实际工作中还有一种更隐蔽的情况:条件变量被改为意想不到的类型,比如在某个分支中把数字i变成了字符串,导致i < 10永远不成立。所以建议在 while 循环条件里写明确的比较表达式,避免用一个大布尔变量被很多地方改来改去。

有时候你会遇到“程序卡住但 CPU 不飙高”的情况,那多半不是死循环,而是等待外部 IO,比如网络请求没有超时、文件读取被阻塞。你需要区分清楚:死循环通常 CPU 占用率高,IO 阻塞通常 CPU 占用率低。排查思路完全不一样。

6.4 循环变量作用域和后续变量覆盖

Python 的循环变量不像某些语言那样拥有局部作用域,它在循环结束后仍然是可见的。比如:

for i in range(5): pass print(i) # 4

这个特性在某些场景下很方便,但也可能造成麻烦。假如你前面用循环变量result存了一批数据,后面又写了另一个 for 循环,循环变量也叫result,前面的值就会被覆盖。尤其在 Jupyter Notebook 这种交互式环境里,循环变量的残留很容易导致后续代码出现诡异问题。

我的习惯是:循环变量的命名要有意义,尽量用item、key、value这类单数名词,避免用temp、data这种含糊名字。这样可以减少覆盖变量的风险。如果循环内部有临时计算结果,尽量用不同名字保存,而不是重复使用一个变量。

6.5 异常处理放在循环里还是循环外

这个选择会直接影响程序行为。如果 try/except 放在循环内部,那么一次迭代出错会被捕捉,后续迭代继续执行:

for item in data: try: process(item) except ValueError: print("跳过", item)

如果 try/except 放在循环外部,那么任何一个 item 抛出异常都会直接退出循环,不再处理后面的数据:

try: for item in data: process(item) except ValueError: print("整个循环中断")

实际项目里,拉取批量接口时,我一般会把单条数据处理的异常放在循环内部,保证一条失败不会拖垮整个批次。但如果你需要“一批任务要么全部成功,要么全部标记失败”的语义,那就把异常放在循环外,或者收集所有异常统一处理。没有对错,关键看业务需求。

6.6 常见循环问题速查

现象原因解决方案
遍历列表删除元素后,部分元素被跳过删除导致索引前移遍历副本或用倒序删除
for 第二次遍历生成器没有结果生成器是一次性的改用列表或重新创建生成器
while 循环不退出条件变量未更新在循环体内更新条件变量,或添加最大次数
两层 for 里 break 只跳出内层break 只作用于最近一层用标志变量或抽函数 return
找元素是否存在时循环很慢列表in是 O(n)改用集合 set
循环中调用 len() 等不变函数重复计算提到循环外赋值给局部变量
循环结束后变量残留Python 循环变量无独立作用域使用不冲突的变量名
单条数据异常导致整个循环停止异常处理在循环外把 try/except 移到循环体内

6.7 调试循环的一些小工具

当你面对一个很复杂的循环,怎么高效定位问题?我自己的习惯是三个招式。

第一,打印法。在循环体关键位置打印变量的值。Python 的print是最原始但也最直接的调试手段。不过别在生产代码里乱留打印语句,可以用logging.debug()替代。

第二,pdb断点调试。在循环前设置断点,然后单步执行,逐行观察变量变化。命令很简单:

import pdb for i in range(10): pdb.set_trace() print(i)

运行到pdb.set_trace()会进入交互式调试,你可以输入n继续下一行,p i打印变量,c继续循环。

第三,给循环添加进度显示。如果循环次数很多,比如几百万次,直接用print会很刷屏,我一般用tqdm:

from tqdm import tqdm for i in tqdm(range(1000000)): pass

这个库能显示进度条、剩余时间、每秒迭代次数。在处理大批量文件、训练模型、数据清洗的时候,进度条能让你快速判断循环是“正在跑”还是“卡死了”。如果不想引入第三方库,也可以在每 N 次迭代的时候打印一次当前进度,比如:

for i in range(total): if i % 10000 == 0: print(f"进度 {i}/{total}")

这种方式开销很小,但能给你一个程序还在呼吸的感觉。

7. 最后再分享一点个人体会

循环这个东西,看着基础,但在实际项目里几乎无处不在。我在写量化交易策略的时候,经常要循环回测历史行情数据;写爬虫时要用循环拉取多页内容;写数据处理脚本时要用循环清洗每一行数据。可以说,循环写得好不好,直接决定代码能不能维护。

我个人在写循环的时候,会先想清楚三件事:这次循环是在“遍历集合”还是“等待条件”,需不需要提前退出,以及循环过程中的数据结构选对没有。想清楚之后,再决定用 for 还是 while,要不要 break/else,能不能用推导式或者内置函数替代。这些判断比单纯记住语法更重要。

还有一个很小的技巧:循环体里的代码尽量短。如果循环体超过 10 行,我会考虑把里面的逻辑抽成函数,比如process_item(item)。这样循环本身变成一层薄薄的壳,逻辑清晰,也方便测试。尤其在 for 循环里,函数调用看起来多了一次开销,但带来的可维护性提升远超那点性能损耗。

最后再分享一个我自己用得很顺的小习惯:写循环时,如果发现代码里出现了一堆下标 i、j、k,就要警惕是不是在“用 Python 写 C”。Python 的循环魅力在于数据流和迭代器,尽量用 Python 的方式去表达,你会发现代码简短、清爽得多。希望这份极简整理能帮你少踩几个坑。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询