python迭代器和生成器

迭代器

定义

迭代器是实现了迭代器协议的一种对象

迭代器协议

迭代器协议是 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.

 总结

  • 迭代器是更底层的概念,提供了遍历数据的基本机制。

  • 生成器是基于迭代器的一种更高级、更简洁的实现方式,适合大多数需要惰性求值的场景。

  • 在实际开发中,生成器通常更常用,因为它更简洁、易读,并且能很好地处理大数据量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值