学习 Python迭代器与生成器的至强指南
学习 Python 的过程中,你可能会听到“迭代器(iterator)”和“可迭代对象(iterable)”这两个术语。
它们听起来很像,意思也有点接近,但其实是不同的概念。
今天就带你搞清楚它们到底是什么,并用一些生活中的例子帮助你理解。

什么是迭代器?
迭代器是可以逐步取出数据的对象。它们的主要特点是记得上一次取到哪里,并能继续往下取。
我们来看看一个简单的例子:
people = ["小明", "小红", "小刚"] # 定义一个包含三个名字的列表
这是一个包含三个人名的列表。如果想把它变成迭代器,只需要用 Python 自带的 iter()
函数:
people_iterator = iter(people) # 使用 iter() 将列表转化为迭代器
现在,people_iterator
就是一个迭代器了。
那么迭代器有什么特别之处呢?
迭代器的特点
-
1. 按需取数据:
迭代器不会一次性加载所有数据,而是需要的时候再取。例如:print(next(people_iterator)) # 输出 "小明" print(next(people_iterator)) # 输出 "小红"
每次调用
next()
,都会返回下一个值。 -
2. 不可回头:
迭代器是一次性的,一旦取出一个元素,就不能再返回。例如:print(list(people_iterator)) # 输出 ["小刚"],迭代器剩余的部分被转为列表 print(list(people_iterator)) # 输出 [],因为迭代器已经用完了
-
3. 节省内存:
因为迭代器不会一次性加载所有数据,所以它特别适合处理大量数据。想象一下,如果你要处理一百万条数据,而不是一次性加载到内存中,迭代器会让程序运行得更高效。
StopIteration 异常
当迭代器中的数据取完后,再调用 next()
,会抛出一个特殊的错误:
try:
print(next(people_iterator)) # 再次调用 next(),但迭代器已耗尽
except StopIteration: # 捕获 StopIteration 异常
print("没有数据了!")
什么是生成器?
生成器是创建迭代器的一种简单方法。只需要用 yield
关键字,就可以轻松写出一个生成器函数:
def generate_numbers(n):
for i in range(n): # 循环生成从 0 到 n-1 的数字
yield i # 使用 yield 暂停函数执行并返回值
调用这个函数会得到一个生成器对象:
gen = generate_numbers(3) # 创建生成器对象
print(next(gen)) # 输出 0
print(next(gen)) # 输出 1
生成器其实就是特殊的迭代器。也就是说,所有生成器都是迭代器,但并不是所有迭代器都是生成器。
生成器还有一个特别的地方,就是它能让代码更简洁。
例如,生成一个斐波那契数列:
def fibonacci(n):
a, b = 0, 1 # 初始化斐波那契数列的前两个数字
for _ in range(n): # 循环生成 n 个数字
yield a # 返回当前的数字
a, b = b, a + b # 更新为下一个斐波那契数
使用生成器生成并输出前 10 个斐波那契数:
for num in fibonacci(10):
print(num)
你会发现,生成器让复杂的逻辑看起来清晰易懂。
什么是可迭代对象?
可迭代对象是可以用来创建迭代器的对象。
常见的可迭代对象有:列表、元组、集合、字符串、字典等。
只要一个对象能用 iter()
函数转成迭代器,它就是可迭代的。例如:
my_list = [1, 2, 3] # 定义一个列表
iterator = iter(my_list) # 使用 iter() 将列表转化为迭代器
但有些东西,比如整数,是不可迭代的:
num = 42 # 整数类型
iterator = iter(num) # 会报错:TypeError,因为整数不可迭代
判断是否是可迭代对象
判断一个对象是否可迭代有一个简单的方法,就是看它能不能用 for
循环。比如:
for char in "hello": # 遍历字符串的每个字符
print(char) # 每次输出一个字母
如果一个对象能用 for
循环,那它一定是可迭代的。
迭代器和可迭代对象的区别
-
1. 核心区别: -
• 可迭代对象是一个“容器”,可以用来生成迭代器。 -
• 迭代器是一个可以逐步返回数据的“工具”。
-
-
2. 使用方式: -
• 可迭代对象可以直接用 for
循环:for name in ["小明", "小红", "小刚"]: # 遍历列表 print(name)
-
• 迭代器需要用 next()
:names = iter(["小明", "小红", "小刚"]) # 将列表转换为迭代器 print(next(names)) # 输出第一个元素 "小明"
-
-
迭代器和生成器的实际用法
-
1. 逐行读取大文件
如果我们需要处理一个很大的文件,可以用生成器按需读取:def read_large_file(file_path): with open(file_path) as file: # 打开文件 for line in file: # 按行读取文件内容 yield line.strip() # 去掉行末的换行符并返回
这种方法只会一次读取一行,避免内存不足。
-
2. 自定义迭代器
如果需要更复杂的迭代逻辑,可以自己写一个迭代器类:class Counter: def __init__(self, start, end): # 初始化起始值和结束值 self.current = start self.end = end def __iter__(self): # 定义可迭代协议 return self def __next__(self): # 定义如何生成下一个值 if self.current > self.end: raise StopIteration # 数据用完时抛出异常 value = self.current self.current += 1 # 增加当前值 return value # 返回当前值
使用自定义迭代器:
counter = Counter(1, 5) # 创建计数器实例 for num in counter: print(num) # 输出从 1 到 5 的数字
-
3. 生成数学序列
除了斐波那契数列,你还可以用生成器生成各种数学序列,比如质数序列:def prime_numbers(limit): def is_prime(num): # 判断一个数是否是质数 if num < 2: return False for i in range(2, int(num**0.5) + 1): # 试除法 if num % i == 0: return False return True count = 0 num = 2 # 从 2 开始寻找质数 while count < limit: if is_prime(num): yield num # 生成一个质数 count += 1 # 计数加一 num += 1 # 检查下一个数
使用生成器生成前 10 个质数:
for prime in prime_numbers(10): print(prime)
-
总结
-
• 迭代器 是一种可以逐步取数据的对象,用于节省内存。 -
• 生成器 是创建迭代器的简便方法,用 yield
编写。 -
• 可迭代对象 是一种可以用来生成迭代器的容器,比如列表和元组。
通过这些知识,你不仅可以更高效地处理数据,还能更深入地理解 Python 的强大之处!
来源:猫十