Python(for循环)

1.了解for循环

1. 什么是 for 循环?

在许多语言中(如 C、Java),for 循环是基于计数器的:

C语言

复制代码
int main()
{
    for(int i = 0; i < 10 ; i++)
    {
        printf("%d\n",i);
    }
}

但 Python 的 for 完全不同:它是迭代器风格的循环,直接遍历一个可迭代对象中的每个元素,而不需要手动管理索引。

Python

复制代码
for item in [1, 2, 3, 4, 5]:
    print(item)

这种设计的优点:

  • 简洁:不需要写索引、边界条件、步长。

  • 安全:不会出现"差一错误"(off-by-one error)。

  • 通用:可以遍历任何可迭代对象(列表、字符串、字典、文件、生成器等)。

2. 可迭代对象与迭代器

  • 可迭代对象 :凡是可以用 for...in 直接循环的对象,如列表、元组、字符串、字典、集合、文件对象、range、生成器等。

  • 迭代器 :实现了 __next__() 方法的对象,可以逐个产生元素。for 循环内部会自动将可迭代对象转换成迭代器,然后反复调用 __next__() 直到捕获 StopIteration 异常。

你可以手动模拟 for 循环的行为:

复制代码
fruits = ["苹果", "香蕉", "橙子"]
iterator = iter(fruits)   # 获取迭代器
while True:
    try:
        fruit = next(iterator)
        print(fruit)
    except StopIteration:
        break

3. for 循环的语法结构

复制代码
for 变量 in 可迭代对象:
    循环体代码块
else:
    循环正常结束(没有被 break 打断)时执行
  • 变量:每次循环被赋值为可迭代对象中的下一个元素。

  • 循环体:缩进的代码块,对每个元素执行一次。

  • else 子句(可选):仅在循环没有被 break 终止时执行。通常用于"如果没找到"的场景。

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

    输出:0 1 2

2.代码执行顺序

1. 基本执行流程

复制代码
for i in [10, 20, 30]:
    print("开始循环")
    print(i)
    print("结束本次循环")
print("循环结束")

执行顺序:

  1. 将可迭代对象 [10,20,30] 转换成迭代器。

  2. 取出第一个元素 10,赋值给 i

  3. 执行循环体(print("开始循环")print(10)print("结束本次循环"))。

  4. 回到迭代器,取出下一个元素 20,赋值给 i,再次执行循环体。

  5. 重复直到迭代器耗尽(抛出 StopIteration)。

  6. 跳出循环,执行 print("循环结束")

2. range 对象的惰性求值

range(start, stop, step) 不会一次性生成所有数字,而是返回一个惰性的 range 对象,它只在迭代时逐个生成数字。这节省内存,尤其适合大范围循环。

复制代码
for i in range(10**9):   # 不会占用大量内存
    if i == 5:
        break

3. 循环中改变可迭代对象的风险

不要在遍历列表的同时修改列表长度(添加或删除元素),这会导致元素被跳过或重复迭代。

复制代码
lst = [1, 2, 3, 4]
for x in lst:
    if x % 2 == 0:
        lst.remove(x)   # 危险!跳过某些元素
print(lst)   # 可能得到 [1, 3] 还是 [1, 3, 4]?取决于实现,不可预测。

正确做法:遍历副本 for x in lst[:]: 或者用列表推导式创建新列表。

4. breakcontinueelse 的执行顺序

  • break:立即终止整个循环,跳过 else 子句

  • continue:跳过本次循环剩余代码,进入下一次迭代

  • else:仅在循环正常结束(没有遇到 break)时执行。

    for n in range(2, 10):
    for x in range(2, n):
    if n % x == 0:
    print(n, '=', x, '*', n//x)
    break
    else:
    print(n, '是素数')

输出会列出素数和合数。这里的 else 属于内层 for,当内层循环没有被 break 时执行。

5. 理解 for 循环对迭代器的隐式调用

for 循环实质上等价于:

复制代码
iterator = iter(iterable)
while True:
    try:
        var = next(iterator)
    except StopIteration:
        break
    else:
        # 循环体
        ...

了解这个等价关系有助于理解为什么在循环中对 iterable 进行某些操作(如重新赋值)不会影响迭代器。

3.遍历---多种方式遍历各自数据结构

1. 遍历列表、元组、字符串

复制代码
colors = ['红', '绿', '蓝']
for c in colors:
    print(c)

# 遍历字符串中的字符
for ch in "Python":
    print(ch)

2. 使用 enumerate() 同时获取索引和值

当需要知道当前元素的索引时,不要手动维护计数器,用 enumerate

复制代码
for idx, fruit in enumerate(['苹果', '香蕉', '橙子']):
    print(f"{idx}: {fruit}")   # 0: 苹果, 1: 香蕉, 2: 橙子

可以指定起始索引:enumerate(列表, start=1)

3. 遍历多个列表:zip()

同时遍历两个或多个等长的可迭代对象:

复制代码
names = ['Alice', 'Bob', 'Charlie']
scores = [85, 92, 78]
for name, score in zip(names, scores):
    print(f"{name} 得分 {score}")

如果长度不一致,zip 会以最短的为准。如果需要以最长为准,可以使用 itertools.zip_longest

4. 遍历字典

  • 遍历键:for key in dict:for key in dict.keys():

  • 遍历值:for value in dict.values():

  • 遍历键值对:for key, value in dict.items():

复制代码
person = {'name': '张三', 'age': 30, 'city': '北京'}
for k, v in person.items():
    print(f"{k} -> {v}")

5. 遍历文件对象

文件对象是可迭代的

复制代码
with open('file.txt') as f:
    for line in f:        # 不会一次性读入整个文件
        print(line.strip())

这是处理大文件最推荐的方式。

6.使用 range() 进行数字循环

虽然不常用,但你也可以用索引方式遍历列表:

复制代码
fruits = ['苹果', '香蕉', '橙子']
for i in range(len(fruits)):
    print(f"{i}: {fruits[i]}")

enumerate 更优。

7.反向遍历:reversed()

复制代码
for item in reversed([1, 2, 3]):
    print(item)   # 3,2,1

8.带条件的遍历:结合 if

可以在循环体内加条件,也可以使用生成器表达式过滤:

复制代码
# 方法1
for x in range(20):
    if x % 2 == 0:
        print(x)

# 方法2:先生成偶数列表再遍历
for x in (x for x in range(20) if x % 2 == 0):
    print(x)

# 方法3:使用 filter
for x in filter(lambda x: x % 2 == 0, range(20)):
    print(x)

4.性能、惯用法与常见陷阱

1. for 循环与 while 循环的选择

  • for 适用于遍历已知可迭代对象(元素个数明确或可迭代)。

  • while 适用于基于条件循环(不知道何时终止,例如用户输入直到合法)。

2. 列表推导式 vs for 循环

列表推导式是 for 循环的一种高效替代,用于生成新列表。它通常比等价的 for 循环更快,因为内部使用专用 C 级实现。

复制代码
# 慢
squares = []
for x in range(1000):
    squares.append(x**2)

# 快
squares = [x**2 for x in range(1000)]

3. 避免在循环中重复计算不变量

复制代码
# 不推荐
for i in range(len(data)):
    process(i, len(data))   # len(data) 每次都要计算

# 推荐
n = len(data)
for i in range(n):
    process(i, n)

4. 使用 itertools 模块实现更复杂的遍历

  • itertools.chain:将多个可迭代对象串联。

  • itertools.product:嵌套循环的笛卡尔积。

  • itertools.combinations / permutations:组合与排列。

  • itertools.cycle:无限循环遍历。

避免多层嵌套循环

复制代码
from itertools import product
for i, j in product(range(3), range(3)):
    print(i, j)   # 输出9对

5. 生成器函数与 yield ------ 自定义迭代器

当你需要复杂的遍历逻辑时,可以编写生成器函数:

复制代码
def fibonacci(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

for num in fibonacci(10):
    print(num)

6. for 循环的性能特性

  • Python 的 for 循环比 C 语言慢,因为每次迭代都要进行对象创建和类型检查。

  • 对于数值密集型循环,考虑使用 NumPy 向量化操作。

  • 对于纯 Python 循环,尽量将工作移动到内置函数(如 sum, map, filter)或列表推导式中。

7. 常见陷阱总结

陷阱 后果 解决方案
遍历时修改列表长度 跳过或重复元素 遍历副本 lst[:],或用列表推导式过滤
忘记 enumerate,手动维护索引 代码冗余,易出错 使用 enumerate
使用 range(len(lst)) 而不是直接遍历 不 Pythonic,且慢 直接用 for x in lst:enumerate
在循环中调用函数却没有缓存结果 重复计算,效率低 将不变结果提到循环外
误用 else 子句(以为每次都会执行) 逻辑错误 牢记 else 仅在无 break 时执行
在循环内定义大对象却未复用 浪费内存和 CPU 将定义移到循环外

感谢你的观看,期待我们下次再见!

相关推荐
咱那飘逸的长发1 小时前
Trae java项目配置全局maven和jdk
java·python·maven
Ada大侦探1 小时前
新手小白学习数据分析01----数据分析师???& 数据分析思维学习
android·学习·数据分析
大学生小郑1 小时前
CMOS 传感器堆叠结构
图像处理·学习·音视频·视频
爱上好庆祝1 小时前
学习js的第六天(js基础的结束)
开发语言·前端·javascript·学习·ecmascript
码界筑梦坊2 小时前
116-基于Flask的健身房会员锻炼数据可视化分析系统
python·信息可视化·数据分析·flask·毕业设计
wcy_10112 小时前
QCoder智能生成Excel数据清洗与可视化代码
python·excel
ErizJ2 小时前
Kubernetes|学习笔记
笔记·学习·kubernetes
rOuN STAT2 小时前
Golang 构建学习
开发语言·学习·golang
财经资讯数据_灵砚智能2 小时前
基于全球经济类多源新闻的NLP情感分析与数据可视化(夜间-次晨)2026年5月2日
人工智能·python·信息可视化·自然语言处理·ai编程