Python迭代器与生成器全解析:让你的代码高效又优雅!
2025年5月21日 22:43
一、什么是迭代器(Iterator)?
1.1 迭代器的定义
迭代器是一个可以记住遍历位置的对象。它实现了两个方法:__iter__()
和 __next__()
。
任何实现了这两个方法的对象都可以称为迭代器。
1.2 为什么需要迭代器?
- 节省内存:不需要一次性加载所有数据
- 惰性计算:按需生成数据,适合处理大数据集
- 代码简洁:统一的遍历接口
1.3 可迭代对象与迭代器的区别
-
可迭代对象(Iterable):实现了
__iter__()
方法,如list、tuple、dict、str等 -
迭代器(Iterator):实现了
__iter__()
和__next__()
方法
1.4 例子:for循环的本质
nums = [1, 2, 3]
it = iter(nums) # 获取迭代器
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
# print(next(it)) # StopIteration异常
二、自定义迭代器
2.1 实现一个自定义迭代器
class MyRange:
def __init__(self, start, end):
self.current = start
self.end = end
def __iter__(self):
return self
def __next__(self):
if self.current < self.end:
num = self.current
self.current += 1
return num
else:
raise StopIteration
for i in MyRange(1, 4):
print(i) # 输出 1 2 3
三、生成器(Generator)
3.1 生成器的定义
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
生成器是一种特殊的迭代器,用于生成序列。它更简单、更强大,使用yield
语句返回数据。
3.2 生成器函数
def my_generator():
yield 1
yield 2
yield 3
for value in my_generator():
print(value) # 输出 1 2 3
3.3 生成器表达式
gen = (x * x for x in range(3))
for num in gen:
print(num) # 输出 0 1 4
四、生成器的高级用法
4.1 惰性求值与大数据处理
生成器不会一次性生成所有数据,而是每次请求时才生成下一个值,非常适合处理大文件或无限序列。
def read_large_file(file_path):
with open(file_path) as f:
for line in f:
yield line.strip()
4.2 生成器的send()
、throw()
和close()
生成器不仅可以next()
,还可以通过send()
向生成器内部传值。
def echo():
received = yield "start"
while True:
received = yield received
gen = echo()
print(next(gen)) # 输出 start
print(gen.send("hello")) # 输出 hello
print(gen.send("world")) # 输出 world
五、迭代器与生成器的最佳实践
5.1 用生成器处理大数据
def count_up_to(n):
count = 1
while count <= n:
yield count
count += 1
for num in count_up_to(1000000):
pass # 不会占用太多内存,因为每次只生成一个数字
5.2 组合生成器
def gen1():
yield from range(3)
def gen2():
yield from gen1()
yield 100
for i in gen2():
print(i) # 输出 0 1 2 100
5.3 反向迭代
list1 = [1,2,3,4,5]
for num1 in reversed(list1) : # Python 中有内置的函数 `reversed()`
print ( num1 , end = ' ' )
注意:反向迭代仅仅当对象的大小可预先确定或者对象实现了 __reversed__()
的特殊方法时才能生效。 如果两者都不符合,那你必须先将对象转换为一个列表才行
5.4 同时迭代多个序列
names = ['laingdianshui', 'twowater', '两点水']
ages = [18, 19, 20]
for name, age in zip(names, ages): #
print(name,age)
注意:zip(a, b) 会生成一个可返回元组 (x, y) 的迭代器,其中 x 来自 a,y 来自 b。 一旦其中某个序列到底结尾,迭代宣告结束。 因此迭代长度跟参数中最短序列长度一致
六、常见误区与注意事项
- 生成器只能遍历一次,遍历完后就“耗尽”了
- 不要滥用生成器表达式,复杂逻辑建议用生成器函数
- StopIteration异常是生成器和迭代器结束的标志
最后
如果你觉得这篇文章有用,记得点赞、关注、收藏,学Python更轻松!!