迭代器
定义
迭代器是实现了迭代器协议的一种对象
迭代器协议
迭代器协议是 Python 内部实现惰性求值(Lazy Evaluation)和高效数据访问的核心机制。它定义了对象如何以迭代器的形式被逐一访问,而无需一次性加载所有数据。
迭代器协议要求对象必须实现以下两个方法:
-
__iter__()
方法:返回迭代器本身,使用iter()函数会调用此方法,并且for循环会隐式调用此方法。 -
__next__()
方法:返回迭代器的下一个值,当调用next()函数时,会调用此方法。如果还有数据未返回,则返回下一个值,如果数据已耗尽,则抛出StopIteration
异常,通知迭代结束。
迭代器与可迭代对象
可迭代对象(Iterable):
-
它是能够一次返回一个成员的对象,也就是可以 for…in 遍历的
-
所有的序列类型,都是可迭代对象,如 list、str、tuple,还有映射类型 dict、文件对象等非序列类型也是可迭代对象;
-
自定义对象在实现了 iter() 方法或者实现了 getitem() 方法后,也可以成为可迭代对象
-
iter()方法接受一个可迭代对象,该方法的返回值是一个迭代器(Iterator)
-
判断是否是可迭代对象的方式是调用 iter(obj),如果不报错,说明是可迭代对象,反之则不是
迭代器(Iterator):
-
一个表示数据流的对象,可通过重复调用 next(或使用内置函数next())方法来获取元素。当没有元素存在时,抛出 StopIteration 异常
-
iter(obj)接受一个迭代器作为参数时,返回的是它本身。迭代器一定是一个可迭代对象
-
、一个迭代器必须要实现 iter() 方法。但因为迭代器前提必须是一个可迭代对象,所以只实现 iter() 方法不一定是一个迭代器
注意:迭代的方式有两种,一种是通过下标,即实现 getitem,一种是直接获取值,即实现 iter,两种方式都可通过 for…in 方式进行遍历。也都是可迭代对象
迭代与递归
-
迭代(iteration)是重复反馈
过程的活动,其目的通常是为了接近并到达所需的目标或结果。每一次对过程的重复被称为一次“迭代”,而每一次迭代得到的结果会被用来作为下一次迭代的初始值。 -
递归指在函数的定义中使用函数自身的方法。
简单来理解迭代就是将大问题划分为很多小问题,从小问题出发解决大问题;递归是将从大问题出发类似与剥洋葱一层一层的深入,直到解决最深处的问题,然后在反过来根据最深处的答案去依次解决上一层的问题,直到解决大问题。
实现迭代器
class MyIteror:
def __init__(self,data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index < len(self.data):
result = self.data[self.index]
self.index += 1
return result
else :
raise StopIteration
my_iter = MyIteror([10,25,30])
print(next(my_iter))
print('————')
for value in my_iter:
print(value)
print('————')
print(next(my_iter))
结果
10 ———— 25 30 ————
--------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-11-e60c545832a9> in <module> 18 print(value) 19 print('————') ---> 20 print(next(my_iter)) <ipython-input-11-e60c545832a9> in __next__(self) 11 return result 12 else : ---> 13 raise StopIteration 14 my_iter = MyIteror([10,25,30]) 15 print(next(my_iter)) StopIteration:
可以看到执行next()函数后索引会加1,继续执行for in 语句则会从索引1开始迭代直到结束,继续执行next()函数则会返回StopIteration
生成器
定义
生成器(Generator)是一种特殊的迭代器,它允许定义一个函数,该函数可以按需生成值,而不是一次性生成所有值并存储在内存中。生成器使用 yield
关键字来返回一个值,并在每次调用时从上一次 yield
的位置继续执行。
工作原理
每次调用生成器的 __next__()
方法(或通过 next()
函数)时,生成器函数会从上次暂停的位置继续执行,直到遇到下一个 yield
语句。生成器可以暂停和恢复执行,而不需要保存完整的执行状态。
特点
-
生成器不会一次性生成所有数据,而是按需生成。
-
生成器在每次
yield
后会保存当前的执行状态,包括局部变量和执行位置。 -
生成器只能遍历一次,遍历结束后会抛出
StopIteration
异常。
创建生成器
生成器函数
使用 yield
关键字定义函数。
def count(max_val):
count = 1
while count <= max_val:
yield count
count += 1
for i in count(5):
print(f"生成器内的值为:{i}")
输出
生成器内的值为:1 生成器内的值为:2 生成器内的值为:3 生成器内的值为:4 生成器内的值为:5
生成器表达式
类似于列表推导式,但使用圆括号 ()
gen = (x**2 for x in range(1,5))
print(list(gen))
输出
[1, 4, 9, 16]
生成器高级用法
发送值到生成器
使用 send(value)
方法可以向生成器发送一个值,该值会成为 yield
表达式的返回值。
def echo():
while True:
value = yield
print(f"接收:{value}")
gen = echo()
next(gen)
gen.send("第一个值")
gen.send("第二个值")
输出
接收:第一个值 接收:第二个值
关闭生成器
使用 close()
方法可以关闭生成器,之后任何对生成器的调用都会引发 StopIteration
异常。
def count_up_to(max_value):
for i in range(1, max_value + 1):
yield i
gen = count_up_to(5)
print(next(gen)) # 输出: 1
gen.close()
try:
print(next(gen))
except StopIteration:
print("Generator is closed.")
输出
1 Generator is closed.
总结
-
迭代器是更底层的概念,提供了遍历数据的基本机制。
-
生成器是基于迭代器的一种更高级、更简洁的实现方式,适合大多数需要惰性求值的场景。
-
在实际开发中,生成器通常更常用,因为它更简洁、易读,并且能很好地处理大数据量。