迭代器
迭代器
一、介绍
迭代
迭代是指重复执行某个过程。在编程中,迭代常用于遍历数据结构中的每一个元素,比如列表、元组或字符串。
可迭代对象
在 Python 中,可迭代对象是指可以使用 for
循环遍历的对象,比如列表、元组、字符串、字典和集合。这些对象都有一个内置方法 __iter__()
,使得它们可以返回一个迭代器。
my_list = [1, 2, 3]
for item in my_list:
print(item)
1
2
3
二、迭代器
迭代器是实现了迭代协议的对象,它们有两个方法:__iter__()
和 __next__()
。__iter__()
返回迭代器对象本身,而 __next__()
返回容器的下一个元素,如果没有元素了,就会引发 StopIteration
异常。
通过内置函数,可以将 list
转为迭代器:
my_list = [1, 2, 3]
it = iter(my_list)
print(next(it))
print(next(it))
print(next(it))
print(next(it)) # 抛出 StopIteration 异常
1
2
3
Traceback (most recent call last):
File ".../test_iter.py", line 6, in <module>
print(next(it)) # 抛出 StopIteration 异常
StopIteration
三、使用场景
节省内存
迭代器是按需生成元素的,这意味着它们不会一次性将所有元素存储在内存中。相比于生成包含所有元素的列表或其他容器,迭代器可以节省大量内存,尤其是在处理大量数据时。
import sys
# 普通列表占用较多内存
my_list = [i for i in range(1000000)]
print(sys.getsizeof(my_list)) # 输出内存大小
# 迭代器占用较少内存
my_iterator = (i for i in range(1000000))
print(sys.getsizeof(my_iterator)) # 输出内存大小
my_iterator = (i for i in range(100000000))
print(sys.getsizeof(my_iterator)) # 输出内存大小
8697472
128
128
可以看出,对于迭代器占用了较少的内存,而且和数量没有关系。
惰性求值
迭代器使用惰性求值策略,即在需要时才生成下一个元素。这种特性使得迭代器在处理流式数据(如读取大文件)时特别有用,因为它们可以逐行读取文件,而不是一次性将整个文件读入内存。
def read_large_file(file_path):
with open(file_path, 'r') as file:
for line in file:
yield line
# 使用迭代器逐行读取大文件
for line in read_large_file('large_file.txt'):
print(line.strip())
可无限序列
迭代器可以用于生成无限序列,比如斐波那契数列或无穷递增序列,而不会耗尽内存。这是因为迭代器不会一次性生成所有元素,只会在需要时生成下一个元素。
class Fibonacci:
def __iter__(self):
self.a = 0
self.b = 1
return self
def __next__(self):
fib = self.a
self.a, self.b = self.b, self.a + self.b
return fib
# 创建一个迭代器实例
fib_iter = Fibonacci()
# 使用迭代器生成斐波那契数列
for num in fib_iter:
if num > 10:
break
print(num)
0
1
1
2
3
5
8
在迭代的过程中实时计算,而不是提前都计算好。
四、生成器
生成器是一种特殊的迭代器,它通过 yield
关键字一次返回一个值。生成器比普通迭代器更简单易用,因为它不需要实现 __iter__()
和 __next__()
方法。
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen)) # 抛出 StopIteration 异常
1
2
3
Traceback (most recent call last):
File ".../test_iter.py", line 10, in <module>
print(next(it)) # 抛出 StopIteration 异常
StopIteration
生成器在调用时不会立即执行,而是返回一个生成器对象。每次调用 next()
方法时,生成器函数会继续执行,直到遇到 yield
语句,返回 yield
后面的值。再次调用 next()
时,生成器会从上次暂停的地方继续执行。