9 minutes
循环结构与迭代
条件判断让程序有了决策能力,而循环让程序能够重复执行代码块。循环是编程中最强大的工具之一——它让我们能用几行代码处理成千上万的数据。
Python 提供两种主要的循环结构:for 循环(用于遍历可迭代对象)和 while 循环(用于条件控制)。
for 循环
for 循环用于遍历可迭代对象(如列表、元组、字符串、字典、集合等)。
基本语法
# for 循环的基本结构
fruits = ["苹果", "香蕉", "橙子"]
for fruit in fruits:
print(f"我喜欢吃{fruit}")
# 输出:
# 我喜欢吃苹果
# 我喜欢吃香蕉
# 我喜欢吃橙子
遍历不同类型的序列
# 遍历字符串
for char in "Python":
print(char, end=" ")
print() # P y t h o n
# 遍历元组
for color in ("red", "green", "blue"):
print(color, end=" ")
print() # red green blue
# 遍历集合(顺序不确定)
for num in {3, 1, 4, 1, 5, 9}:
print(num, end=" ")
print() # 1 3 4 5 9(自动去重,顺序可能不同)
# 遍历字典(默认遍历键)
student = {"name": "张三", "age": 20, "score": 85}
for key in student:
print(key, end=" ")
print() # name age score
# 遍历字典的键值对
for key, value in student.items():
print(f"{key}: {value}")
# name: 张三
# age: 20
# score: 85
range() 函数
range() 是 Python 内置的序列生成器,常用于 for 循环:
# range(stop):从 0 到 stop-1
for i in range(5):
print(i, end=" ")
print() # 0 1 2 3 4
# range(start, stop):从 start 到 stop-1
for i in range(2, 6):
print(i, end=" ")
print() # 2 3 4 5
# range(start, stop, step):指定步长
for i in range(0, 10, 2):
print(i, end=" ")
print() # 0 2 4 6 8
# 倒序
for i in range(5, 0, -1):
print(i, end=" ")
print() # 5 4 3 2 1
# range() 用于重复执行固定次数
for _ in range(3): # _ 表示"我们不关心这个变量的值"
print("Hello!")
# Hello!
# Hello!
# Hello!
enumerate() 获取索引
当我们遍历序列时,经常同时需要索引和值:
# 传统方式(不推荐)
fruits = ["苹果", "香蕉", "橙子"]
for i in range(len(fruits)):
print(f"{i}: {fruits[i]}")
# 使用 enumerate()(推荐)
fruits = ["苹果", "香蕉", "橙子"]
for i, fruit in enumerate(fruits):
print(f"{i}: {fruit}")
# 0: 苹果
# 1: 香蕉
# 2: 橙子
# 指定起始索引
for i, fruit in enumerate(fruits, start=1):
print(f"{i}. {fruit}")
# 1. 苹果
# 2. 香蕉
# 3. 橙子
zip() 并行遍历
zip() 可以同时遍历多个序列:
# 并行遍历
names = ["张三", "李四", "王五"]
scores = [85, 92, 78]
grades = ["B", "A", "C"]
for name, score, grade in zip(names, scores, grades):
print(f"{name}: {score} 分 ({grade})")
# 张三: 85 分 (B)
# 李四: 92 分 (A)
# 王五: 78 分 (C)
# zip() 在最短序列结束时停止
a = [1, 2, 3, 4]
b = ["a", "b", "c"]
for x, y in zip(a, b):
print(f"{x}-{y}", end=" ")
print() # 1-a 2-b 3-c
# 用 zip_longest 处理不等长序列
from itertools import zip_longest
for x, y in zip_longest(a, b, fillvalue=None):
print(f"{x}-{y}", end=" ")
print() # 1-a 2-b 3-c 4-None
# zip() 常用于创建字典
keys = ["name", "age", "city"]
values = ["张三", 20, "北京"]
info = dict(zip(keys, values))
print(info) # {'name': '张三', 'age': 20, 'city': '北京'}
while 循环
while 循环在条件为真时反复执行代码块,适用于不确定迭代次数的场景:
# while 基本语法
count = 0
while count < 5:
print(f"第 {count + 1} 次循环")
count += 1
# 输出:
# 第 1 次循环
# 第 2 次循环
# ...
# 第 5 次循环
while 循环的经典用法
# 1. 用户输入验证(直到输入正确为止)
password = ""
while password != "python123":
password = input("请输入密码: ")
if password != "python123":
print("密码错误,请重试")
print("登录成功!")
# 2. 游戏循环(状态驱动)
import random
score = 0
playing = True
while playing:
dice = random.randint(1, 6)
print(f"掷骰子: {dice}")
score += dice
if dice == 6:
print("再来一次!")
continue
if score >= 30:
playing = False
print(f"游戏结束,总分: {score}")
# 3. 无限循环(通常配合 break 使用)
while True:
cmd = input("请输入命令 (q 退出): ")
if cmd == "q":
break
print(f"执行命令: {cmd}")
break 和 continue
break 用于完全退出循环,continue 用于跳过当前迭代:
# break:找到目标后提前退出
numbers = [3, 7, 1, 9, 4, 6, 2]
target = 9
for num in numbers:
if num == target:
print(f"找到了 {target}!")
break # 找到后立即退出循环
print(f"检查 {num},不是目标")
# 检查 3,不是目标
# 检查 7,不是目标
# 检查 1,不是目标
# 找到了 9!
# continue:跳过某些元素
for num in range(1, 11):
if num % 3 == 0:
continue # 跳过 3 的倍数
print(num, end=" ")
print() # 1 2 4 5 7 8 10
# continue 在 while 中的注意事项
# 在 while 中使用 continue 时别忘了更新循环变量
count = 0
while count < 10:
count += 1
if count % 2 == 0:
continue
print(count, end=" ")
print() # 1 3 5 7 9
break 和 continue 的对比
| 特性 | break | continue |
|---|---|---|
| 作用 | 完全退出循环 | 结束当前迭代,开始下一次 |
| 对 for 的影响 | 终止遍历 | 跳到下一个元素 |
| 对 while 的影响 | 退出循环 | 重新判断条件 |
| 嵌套循环 | 只退出当前层 | 只影响当前层 |
else 子句
Python 的循环可以带 else 子句——当循环正常结束(没有被 break 中断)时执行:
# for-else 用法
def find_item(items, target):
for item in items:
if item == target:
print(f"找到了: {target}")
break
else:
print(f"没找到: {target}") # 只有循环正常遍历完才执行
find_item([1, 2, 3, 4, 5], 3)
# 找到了: 3
find_item([1, 2, 3, 4, 5], 9)
# 没找到: 9
# while-else 用法
count = 0
while count < 3:
user_input = input("输入 'quit' 退出: ")
if user_input == "quit":
print("用户主动退出")
break
count += 1
else:
print("达到最大尝试次数") # 没有 break 才会执行
# 实际应用:素数检查
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
print(f"{n} 不是素数,可被 {i} 整除")
break
else:
print(f"{n} 是素数")
return True
return False
is_prime(17) # 17 是素数
is_prime(15) # 15 不是素数,可被 3 整除
嵌套循环
一个循环内部包含另一个循环叫做嵌套循环:
# 打印乘法表
for i in range(1, 10):
for j in range(1, i + 1):
print(f"{j}x{i}={i*j:2d}", end=" ")
print() # 换行
# 输出:
# 1x1= 1
# 1x2= 2 2x2= 4
# 1x3= 3 2x3= 6 3x3= 9
# ...
# 遍历二维列表
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
for row in matrix:
for element in row:
print(element, end=" ")
print()
# 1 2 3
# 4 5 6
# 7 8 9
# 嵌套循环+条件
# 找出所有和为 10 的数对
pairs = []
for i in range(1, 6):
for j in range(i, 6):
if i + j == 10:
pairs.append((i, j))
print(pairs) # [(4, 6), (5, 5)](注意 range 只到 5)
从嵌套循环中跳出
# break 只退出当前层的循环
for i in range(5):
for j in range(5):
if j == 3:
break # 只退出内层循环
print(f"({i},{j})", end=" ")
print() # 每行都执行
# 要完全退出多层循环:使用标志位
found = False
for i in range(5):
for j in range(5):
if i == 2 and j == 3:
found = True
break
print(f"({i},{j})", end=" ")
if found:
break
print()
# 或者使用 for-else + break 模式
for i in range(5):
for j in range(5):
if i == 2 and j == 3:
break
print(f"({i},{j})", end=" ")
else:
continue # 内层没有 break,继续外层循环
break # 内层 break 了,也退出外层
循环中的迭代技巧
倒序遍历
# 方法1:reversed()
for char in reversed("Python"):
print(char, end=" ")
print() # n o h t y P
# 方法2:负步长切片
for char in "Python"[::-1]:
print(char, end=" ")
print() # n o h t y P
# 倒序遍历列表
fruits = ["苹果", "香蕉", "橙子"]
for fruit in reversed(fruits):
print(fruit, end=" ")
print() # 橙子 香蕉 苹果
排序遍历
# sorted() 返回排序后的新列表
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
for num in sorted(numbers):
print(num, end=" ")
print() # 1 1 2 3 4 5 6 9
# 降序
for num in sorted(numbers, reverse=True):
print(num, end=" ")
print() # 9 6 5 4 3 2 1 1
# 对字典按键排序
student = {"name": "张三", "age": 20, "score": 85}
for key in sorted(student):
print(f"{key}: {student[key]}")
去重遍历
# 使用集合去重
values = [1, 2, 3, 2, 1, 4, 5, 3, 6]
for v in set(values):
print(v, end=" ")
print() # 1 2 3 4 5 6(顺序可能不同)
# 保持顺序去重
def unique(items):
seen = set()
for item in items:
if item not in seen:
seen.add(item)
yield item
for v in unique(values):
print(v, end=" ")
print() # 1 2 3 4 5 6
列表推导式中的循环
列表推导式本质上是 for 循环的简洁形式:
# for 循环方式
squares = []
for x in range(10):
squares.append(x ** 2)
# 列表推导式方式(等价)
squares = [x ** 2 for x in range(10)]
# 带条件的列表推导式
evens = [x for x in range(20) if x % 2 == 0]
# 嵌套循环的列表推导式
pairs = [(x, y) for x in range(3) for y in range(3)]
# [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2), (2,0), (2,1), (2,2)]
# 列表推导式 vs 常规循环的选择
# 简单转换:用推导式
upper_words = [word.upper() for word in words if word]
# 复杂逻辑:用常规循环
results = []
for item in data:
if complex_condition(item):
transformed = complex_transform(item)
if valid(transformed):
results.append(transformed)
实践练习:数据处理
示例1:词频统计
# word_frequency.py
text = """
Python is an interpreted high-level general-purpose programming language.
Python's design philosophy emphasizes code readability with its notable
use of significant indentation. Python is dynamically-typed and garbage-collected.
"""
# 清理和分词
words = text.lower().split()
# 去除标点
import string
cleaned = []
for word in words:
word = word.strip(string.punctuation)
if word:
cleaned.append(word)
# 统计词频
word_count = {}
for word in cleaned:
word_count[word] = word_count.get(word, 0) + 1
# 按频率排序输出(遍历排序结果)
print("词频统计(前10):")
for word, count in sorted(word_count.items(), key=lambda x: x[1], reverse=True)[:10]:
print(f" {word:20s} {count}")
示例2:斐波那契数列
# fibonacci.py
def fibonacci(n):
"""生成前 n 个斐波那契数"""
fib = [0, 1]
for _ in range(2, n):
fib.append(fib[-1] + fib[-2])
return fib[:n]
# 使用 while 实现的生成器版本
def fibonacci_gen(limit):
"""生成不超过 limit 的斐波那契数"""
a, b = 0, 1
while a <= limit:
yield a
a, b = b, a + b
print("前10个斐波那契数:", fibonacci(10))
print("不超过100的斐波那契数:", list(fibonacci_gen(100)))
示例3:购物车计算
# cart.py
cart = [
{"item": "苹果", "price": 5.0, "qty": 3},
{"item": "牛奶", "price": 18.5, "qty": 2},
{"item": "面包", "price": 8.0, "qty": 1},
{"item": "鸡蛋", "price": 0.8, "qty": 12},
]
# 计算总价
total = 0
for product in cart:
subtotal = product["price"] * product["qty"]
total += subtotal
print(f"{product['item']:6s} x {product['qty']:2d} = {subtotal:.2f}")
print(f"{'=' * 20}")
print(f"{'合计':12s} = {total:.2f}")
# 找打折商品
discount_items = [item for item in cart if item["price"] >= 10]
print(f"\n高价商品(>=10元): {[d['item'] for d in discount_items]}")
循环性能提示
1. 避免在循环中重复计算
# 不好的写法:每次循环都计算长度
for i in range(len(items)):
process(items[i])
# 好的写法:长度只计算一次
n = len(items)
for i in range(n):
process(items[i])
# 更 Pythonic
for item in items:
process(item)
2. 用局部变量加速
# 在循环中频繁访问的属性可以提前赋值
import math
# 较慢(每次查找 math.sqrt)
for x in range(1000000):
y = math.sqrt(x)
# 较快(局部变量)
sqrt = math.sqrt
for x in range(1000000):
y = sqrt(x)
3. 列表推导式 vs 手动循环
import time
n = 10000000
# 手动循环
start = time.perf_counter()
result = []
for i in range(n):
result.append(i ** 2)
t1 = time.perf_counter() - start
# 列表推导式
start = time.perf_counter()
result = [i ** 2 for i in range(n)]
t2 = time.perf_counter() - start
print(f"手动循环: {t1:.3f}s")
print(f"推导式: {t2:.3f}s")
print(f"推导式快约 {t1/t2:.1f} 倍")
4. 使用生成器节省内存
# 列表推导式:一次性创建所有元素,占用大量内存
squares_list = [x ** 2 for x in range(10000000)] # 占用约 80MB
# 生成器:惰性求值,几乎不占内存
squares_gen = (x ** 2 for x in range(10000000)) # 几乎不占内存
# 遍历时没区别
for sq in squares_list[:5]:
print(sq, end=" ")
for sq in squares_gen: # 但生成器只能遍历一次
print(sq, end=" ")
if sq >= 16:
break
常见陷阱
1. 遍历时修改列表
# 错误:遍历时删除元素
numbers = [1, 2, 3, 4, 5, 6]
for num in numbers:
if num % 2 == 0:
numbers.remove(num) # 导致跳过元素!
print(numbers) # [1, 3, 5](碰巧正确,但不可靠)
# 正确方法1:创建新列表
numbers = [1, 2, 3, 4, 5, 6]
numbers = [num for num in numbers if num % 2 != 0]
print(numbers) # [1, 3, 5]
# 正确方法2:倒序遍历
numbers = [1, 2, 3, 4, 5, 6]
for num in reversed(numbers):
if num % 2 == 0:
numbers.remove(num)
print(numbers) # [1, 3, 5]
2. 在 for 循环中修改循环变量
# 在 for 循环中修改循环变量不会影响下一次迭代
for i in range(5):
i += 10 # 这个修改不会影响循环
print(i, end=" ")
print() # 10 11 12 13 14(虽然修改了 i,但不影响 range 的下一个值)
# 要改变循环行为,用 while
i = 0
while i < 10:
print(i, end=" ")
if i == 5:
i += 3 # 确实跳过了几次
else:
i += 1
print() # 0 1 2 3 4 5 9
3. while 循环无限循环
# 忘记更新循环变量
count = 0
while count < 5:
print("无限循环!")
# 缺少 count += 1
# 条件永远为真
while True: # 需要确保内部有 break
cmd = input("输入 'q' 退出: ")
if cmd == "q":
break
4. else 子句的误解
# else 在循环正常结束时执行,即使循环一次都没执行
for x in []:
print("不会执行")
else:
print("循环结束了") # 输出!因为循环正常"完成"了
# 当循环条件一开始就不满足时,else 也会执行
count = 10
while count < 5:
print("不会执行")
count += 1
else:
print("while 条件从未满足") # 输出
小结
在这篇文章中,我们学习了:
- for 循环的多种遍历方式:列表、字符串、字典、range()
- enumerate() 获取索引-值对
- zip() 并行遍历
- while 循环的几种经典用法
- break 和 continue 循环控制
- else 子句在循环中的特殊作用
- 嵌套循环和从多层循环中跳出
- 循环中的迭代技巧:倒序、排序、去重
- 性能优化:局部变量、推导式、生成器
下一步
恭喜你完成了"基础入门篇"的所有 8 篇文章!你已经掌握了 Python 编程的核心基础知识——变量、数据类型、运算符、字符串、列表、元组、字典、集合、条件判断和循环。
在接下来的"函数与模块篇"中,我们将学习如何组织代码、定义函数、使用模块,以及文件读写和异常处理等更高级的主题。继续加油!
实践建议:综合运用所学的知识,编写一个学生成绩管理系统,支持添加学生、录入成绩、查看排名、统计平均分等功能。这需要用到列表存储数据、字典表示信息、循环遍历处理、条件判断做决策。
Summary: 循环结构与迭代全面总结。