十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python循环编程:从for/while基础到列表推导式与性能优化

Python循环编程:从for/while基础到列表推导式与性能优化 1. 从“重复劳动”到“自动化思维”为什么循环是编程的基石如果你刚开始接触Python或者任何一门编程语言可能会觉得写代码就是一行一行地告诉计算机做什么。比如你想打印“Hello, World!”三次你可能会老老实实地写三行print(“Hello, World!”)。这没问题但想象一下如果老板让你打印一千次呢或者你需要处理一个包含一万个用户姓名的列表对每个姓名都执行同样的操作这时候一行一行地写代码就变成了不可能完成的任务也完全背离了编程“自动化”和“高效”的初衷。这就是循环Loop存在的意义。它不是什么高深莫测的黑科技而是编程中最基础、最核心的思维方式之一。它的本质就是让计算机自动地、重复地执行一段代码直到满足某个条件为止。掌握了循环你才真正开始从“手动操作员”向“自动化工程师”转变。无论是处理数据、遍历文件、控制游戏角色、还是构建复杂的算法模型循环都无处不在。网络上那些热门的“Python爬虫”、“循环神经网络RNN”、“软件流程的‘定义→执行→度量→改进’循环”其底层逻辑都离不开对循环机制的深刻理解和灵活运用。今天我们就抛开那些复杂的术语回到最根本的地方彻底搞懂Python里的两种循环for循环和while循环。我会用大量你能立刻上手的例子告诉你它们分别用在什么场景怎么写出高效且不易出错的循环代码以及如何避开初学者最容易踩的那些坑。无论你是想用Python做数据分析、写个小工具还是仅仅为了通过一门课程这篇文章都能帮你把“循环”这个地基打牢。2.for循环当你明确知道要“走多少步”时for循环是Python中最常用、也最“优雅”的循环。它的核心思想是遍历一个已知的序列或任何“可迭代对象”对序列中的每一个元素执行相同的操作。这里的“序列”可以是一个列表、一个字符串、一个字典的键或者一个由range()函数生成的数字序列。2.1 基础语法与遍历列表让我们从一个最简单的例子开始。假设你有一个水果列表你想把每种水果都打印出来。fruits [“苹果”, “香蕉”, “橙子”, “葡萄”] for fruit in fruits: print(fruit)运行这段代码你会看到苹果 香蕉 橙子 葡萄这里发生了什么for fruit in fruits:这行代码是循环的“声明”。它告诉Python“嘿我要开始一个循环了。请你从fruits这个列表里按顺序一个一个地取出元素。每次取出的元素暂时就叫它fruit吧。”print(fruit)这是循环的“身体”也就是要重复执行的代码块。注意它前面有4个空格的缩进。在Python中缩进是定义代码块的唯一方式这和其他一些用大括号{}的语言如C、Java完全不同。没有正确的缩进Python就不知道哪些代码属于循环内部。循环会一直执行直到fruits列表里的最后一个元素“葡萄”被处理完然后自动结束。为什么用for因为我们在循环开始前就已经明确知道了要处理的对象fruits列表和要执行的次数列表的长度4次。这种“确定性”是for循环的典型特征。2.2range()函数生成数字序列的利器很多时候我们并不是要遍历一个具体的列表而是想简单地让一段代码重复执行固定的次数。比如想打印10次“加油”。这时候range()函数就派上用场了。range()函数用于生成一个整数序列。它最常用的三种形式是range(stop)生成从0开始到stop-1结束的序列。例如range(5)生成[0, 1, 2, 3, 4]注意不包含5。range(start, stop)生成从start开始到stop-1结束的序列。例如range(2, 6)生成[2, 3, 4, 5]。range(start, stop, step)生成从start开始到stop-1结束步长为step的序列。例如range(0, 10, 2)生成[0, 2, 4, 6, 8]。现在打印10次“加油”就很简单了for i in range(10): print(“第”, i1, “次加油”)输出第 1 次加油 第 2 次加油 ... 第 10 次加油这里i依次取值为0到9。我通过i1让它从1开始计数这样输出更符合我们的阅读习惯。range(10)生成了一个包含10个数字的序列所以循环体也就执行了10次。一个重要的实操心得range()生成的不是一个真正的列表而是一个“范围对象”。你可以把它想象成一个“懒加载”的序列它只在需要的时候才产生下一个数字。这对于生成很大的数字序列比如range(1000000)非常高效因为它不会一次性在内存中创建包含一百万个数字的列表从而节省了大量内存。只有在某些需要列表的特定场景比如打印它你才需要用list(range(10))把它转换成列表。2.3 遍历其他可迭代对象字符串与字典for循环的威力远不止于列表和数字。任何“可迭代”的对象都可以被遍历。遍历字符串字符串本质上是一个字符序列。for char in “Python”: print(char)输出P y t h o n遍历字典默认情况下for循环遍历字典时拿到的是字典的键key。student_scores {“小明”: 90, “小红”: 85, “小刚”: 92} for name in student_scores: print(name, “的分数是”, student_scores[name])输出小明 的分数是 90 小红 的分数是 85 小刚 的分数是 92如果你想直接遍历字典的值value或键值对item可以使用字典的.values()和.items()方法# 只遍历值 for score in student_scores.values(): print(score) # 遍历键值对最常用 for name, score in student_scores.items(): print(f“{name}考了{score}分”) # 使用f-string格式化输出更清晰使用.items()方法同时获取键和值是处理字典数据时最高效、最Pythonic的方式。3.while循环当条件为真时就一直执行如果说for循环是“按图索骥”那么while循环就是“不到黄河心不死”。while循环的核心是只要某个条件为真True就不断地重复执行循环体内的代码。它不关心要循环多少次只关心条件何时变为假False。3.1 基础语法与一个经典例子它的语法更直接while 条件表达式: # 循环体代码一个经典的例子是猜数字游戏secret_number 42 guess None attempts 0 while guess ! secret_number: guess int(input(“猜一个数字1-100”)) attempts 1 if guess secret_number: print(“猜小了”) elif guess secret_number: print(“猜大了”) print(f“恭喜你用了{attempts}次猜对了”)在这个例子里循环的条件是guess ! secret_number。只要用户猜的数字不等于秘密数字这个条件就为真循环就会一直继续不断要求用户输入。直到某一次用户猜对了条件变为假循环结束程序打印出祝贺信息。while循环的关键在于“条件”。这个条件必须在循环的某个时刻发生改变否则循环将永远进行下去成为“无限循环”。在上面的例子中改变条件的操作是guess int(input(...))用户的每次输入都可能使条件变为假。3.2 无限循环与如何跳出忘记在循环体内更新条件是导致无限循环的最常见原因。比如下面这个危险的代码count 0 while count 5: print(count) # 糟糕忘记了 count 1这段代码会不停地打印0直到你强制停止程序通常按CtrlC。为了避免无限循环你必须确保循环体中有改变条件的逻辑。有时我们也需要主动地、在条件尚未满足时提前退出循环。Python提供了两个关键字break和continue。break立即终止整个循环跳转到循环之后的代码。continue跳过本次循环中continue之后的语句直接开始下一次循环。举个例子我们要在一个列表中寻找第一个负数找到就停止numbers [3, 5, -1, 7, 9, -4] for num in numbers: if num 0: print(f“找到第一个负数{num}”) break # 找到后立即跳出循环 print(f“正在检查正数{num}”) print(“搜索结束。”)输出正在检查正数3 正在检查正数5 找到第一个负数-1 搜索结束。可以看到当num为-1时执行了break循环立刻终止后面的数字7, 9, -4都不会再被处理。再来看continue假设我们只想处理列表中的正数numbers [3, 5, -1, 7, 9, -4] for num in numbers: if num 0: continue # 遇到负数跳过本次循环的剩余部分 print(f“处理正数{num}的平方是{num**2}”)输出处理正数3的平方是9 处理正数5的平方是25 处理正数7的平方是49 处理正数9的平方是81当num为-1和-4时continue语句被执行print语句被跳过循环直接进入下一次迭代。注意break和continue在for和while循环中都可以使用。但过度使用它们尤其是嵌套循环中的break可能会让代码逻辑变得难以追踪。我的经验是优先考虑通过优化循环条件来避免使用break如果必须用要确保逻辑非常清晰。3.3while循环的典型应用场景while循环特别适合那些循环次数未知取决于运行时状态的场景。除了猜数字游戏还有读取文件直到末尾虽然用for line in file更常见但while循环配合readline()也能实现。监听事件或用户输入比如一个简单的命令行菜单用户输入“q”才退出。while True: # 故意制造一个无限循环 command input(“请输入命令 (start/stop/quit): “).lower() if command “start”: print(“系统启动...”) elif command “stop”: print(“系统停止...”) elif command “quit”: print(“退出程序。”) break # 用break跳出无限循环 else: print(“未知命令”)轮询等待某个条件满足例如等待一个网络请求返回、等待一个文件被创建等在实际应用中通常会配合time.sleep()避免CPU空转。4.forvswhile如何做出正确的选择很多初学者会困惑到底该用for还是while这里有一个非常实用的判断准则当你明确知道要循环的次数或者要遍历一个固定的集合列表、字符串、字典、range序列等时优先使用for循环。例如处理一个已知长度的列表、重复执行N次操作、遍历字典的所有键值对。for循环的代码意图更清晰更不容易出错因为通常不会陷入无限循环。当你不知道要循环多少次循环的终止取决于某个动态变化的条件时使用while循环。例如等待用户输入特定指令、监控一个不断变化的状态如游戏运行状态、读取数据直到满足某个条件。简单来说for循环用于“遍历”while循环用于“等待”。来看一个对比案例计算1到100的和。 用for循环total 0 for i in range(1, 101): # 明确知道要加100个数 total i print(total)用while循环total 0 i 1 while i 100: # 条件是 i 100 total i i 1 # 必须手动更新计数器否则无限循环 print(total)显然for循环的版本更简洁、更安全因为你不需要手动管理计数器i和担心忘记i 1导致的无限循环。因此在这个场景下for循环是更优的选择。5. 循环的进阶技巧与性能考量掌握了基础我们来看看如何写出更高效、更Pythonic的循环代码。5.1 列表推导式让循环创建列表更优雅列表推导式List Comprehension是Python的一大特色它提供了一种简洁、高效的方式来创建新列表。它的语法就是把一个for循环压缩在一行方括号[]里。传统方式从一个数字列表创建其平方的新列表。numbers [1, 2, 3, 4, 5] squares [] for num in numbers: squares.append(num ** 2) print(squares) # [1, 4, 9, 16, 25]使用列表推导式numbers [1, 2, 3, 4, 5] squares [num ** 2 for num in numbers] print(squares) # [1, 4, 9, 16, 25]一行代码搞定它甚至还可以加入条件判断# 只保留偶数的平方 even_squares [num ** 2 for num in numbers if num % 2 0] print(even_squares) # [4, 16]列表推导式不仅代码更简洁而且在大多数情况下它的执行速度也比传统的for循环追加方式要快因为它的实现更接近底层C代码。对于简单的数据转换和过滤强烈推荐使用。5.2enumerate()在循环中获取索引在for循环遍历列表时有时我们不仅需要元素本身还需要知道这个元素是第几个即索引。一个笨办法是使用range(len(list))fruits [“苹果”, “香蕉”, “橙子”] for i in range(len(fruits)): print(f“第{i}个水果是{fruits[i]}”)但Python提供了更优雅的工具enumerate()函数。它会在遍历序列的同时返回一个包含索引和元素的元组。fruits [“苹果”, “香蕉”, “橙子”] for index, fruit in enumerate(fruits): print(f“第{index}个水果是{fruit}”)你还可以通过start参数指定索引的起始值for index, fruit in enumerate(fruits, start1): print(f“第{index}个水果是{fruit}”)输出就从“第1个水果”开始了。这比手动管理索引变量i要清晰和安全得多。5.3zip()并行遍历多个序列如果你想同时遍历两个或多个列表zip()函数是你的好帮手。它会把多个序列中对应的元素“打包”成一个个元组。names [“小明”, “小红”, “小刚”] scores [90, 85, 92] for name, score in zip(names, scores): print(f“{name}考了{score}分”)如果序列长度不同zip()会以最短的序列为准停止。如果你想以最长的序列为准并用某个值填充缺失项可以使用itertools.zip_longest()需要导入itertools模块。5.4 循环中的性能陷阱与优化循环是程序中最容易产生性能瓶颈的地方之一尤其是嵌套循环。这里有几个原则避免在循环内部做重复计算如果某个值在循环中不变就把它提到循环外面计算。# 不佳 for i in range(10000): result some_heavy_computation() * i # some_heavy_computation()每次循环都执行 # 较佳 constant_value some_heavy_computation() for i in range(10000): result constant_value * i优先使用内置函数和库Python的内置函数如sum(),max(),min()和标准库如NumPy,Pandas通常由C实现速度远超手写的Python循环。对于大规模的数值计算一定要考虑使用NumPy。警惕“平方级”时间复杂度两层嵌套循环的时间复杂度通常是O(n²)当数据量n很大时性能会急剧下降。要时刻思考算法是否有优化的空间。6. 真实场景下的循环应用与排错理论说再多不如看几个实际的应用片段和常见错误。6.1 场景一批量处理文件假设你有一个文件夹里面有很多.txt文件你需要读取每个文件的内容并做处理。import os folder_path “./data_files” for filename in os.listdir(folder_path): if filename.endswith(“.txt”): file_path os.path.join(folder_path, filename) with open(file_path, ‘r’, encoding‘utf-8’) as f: content f.read() # 对content进行处理比如统计字数 word_count len(content.split()) print(f“文件 {filename} 的字数约为{word_count}”)这里用for循环遍历目录下的所有文件通过if判断筛选出.txt文件然后逐个打开处理。with open(...) as f:的写法可以确保文件被正确关闭即使处理过程中发生异常。6.2 场景二实现一个简单的倒计时import time countdown 10 while countdown 0: print(f“倒计时{countdown}秒”) time.sleep(1) # 暂停1秒 countdown - 1 print(“发射”)这是一个典型的while循环应用循环次数由变量countdown控制每次循环后递减。time.sleep(1)让程序等待一秒模拟真实的倒计时。6.3 常见错误与调试缩进错误IndentationError这是Python新手最常犯的错误。循环体必须正确缩进通常是4个空格或一个Tab。混用空格和Tab会导致难以察觉的错误。建议在编辑器中设置“显示空白字符”功能。修改正在遍历的列表这是一个非常危险的陷阱。numbers [1, 2, 3, 4, 5] for num in numbers: if num % 2 0: numbers.remove(num) # 在遍历时删除元素会导致跳过元素或意外结果 print(numbers) # 结果可能不是预期的[1, 3, 5]正确做法遍历原列表的副本或者创建一个新列表。# 方法一遍历副本 for num in numbers[:]: # numbers[:]创建了一个切片副本 if num % 2 0: numbers.remove(num) # 方法二更推荐使用列表推导式创建新列表 numbers [num for num in numbers if num % 2 ! 0]无限循环如前所述确保while循环的条件有机会变为False。在开发时可以先在循环体内加入一个“安全阀”比如限制最大循环次数。max_attempts 1000 attempts 0 while some_condition and attempts max_attempts: # ... 你的逻辑 attempts 1 if attempts max_attempts: print(“警告可能陷入无限循环或条件长时间未满足”)忽略迭代对象的类型对非迭代对象使用for循环会引发TypeError。num 5 for i in num: # TypeError: ‘int’ object is not iterable print(i)确保你循环的对象是列表、字符串、字典、range、文件对象等可迭代对象。循环是编程的肌肉记忆看得再多不如动手写。我建议你打开Python解释器或你的代码编辑器把本文的每一个例子都敲一遍然后尝试修改它们看看会发生什么。比如把for循环改成while循环或者故意写一个无限循环再用CtrlC终止它。只有通过大量的练习你才能深刻理解循环何时该用、怎么用、怎么用好从而让你写的代码真正“活”起来自动化地解决那些重复性问题。
返回列表