python 迭代器与生成器

python 迭代器与生成器

在之前的文章for 循环的本质中已经提及了迭代器协议。
而生成器又是什么呢?和迭代器又有什么关系呢?本文将为你解惑。
先看如下代码

def g():
    for i in range(3):
        yield i
a = g()

上文的代码中,a 就是一个生成器对象。
该对象可以使用如下代码进行迭代

for i in a:
    print(i)

之前文章说过,使用for循环迭代的对象需要实现 __iter__ 方法,并且这个方法需要返回一个
迭代器对象(该对象需要实现 __iter____next__ 方法)。
而如果在__iter__方法中使用yield关键字,将自动返回一个生成器对象。
生成器对象会自动包含上述两方法。
从这种角度来说生成器提供了一种快速实现迭代器协议的方式。
生成器也可以视为一种特殊的迭代器。
定义: 包含yield语句的函数成为生成器函数,当然也有可能是异步生成器函数。
而生成器函数返回的对象就是一个生成器对象。

生成器还能通过另外一种生成器语句定义,如下:

a = (x for x in [1,2,3])

a 就是一个生成器对象。
定义:与推导式相同的语法,但是使用圆括号定义的表达式返回的对象就是生成器对象。
右侧的表达式也称为生成器表达式

那么生成器与迭代器的不同点在哪呢。

print(dir(x for x in range(3)))

['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']

我们可以发现,相比于迭代器,生成器不仅包含__iter__, __next__方法,
还包含close, send, throw等一些重要的方法。
那这三者又是做什么的呢?
我们再来看以下的代码。

def g():
    try:
        for i in range(3):
            try:
                value = yield i
                print(value)
            except Exception as e:
                print(f'except {e}')
    finally:
        print('close')
a = g()
c0 = a.send(None)
c1 = a.send('send_1')
c2 = a.send('send_2')
print(c0, c1, c2)
a.close()

我们知道,一个迭代器,可以使用 next 方法进行迭代。而生成器不止可以使用 next 方法,
还能使用其提供的 send 方法控制生成器函数。
第一个 send(None) 是必须的用于启动生成器函数,执行到 yield i 这一步。
此时函数返回值赋值给 c0 。因为此时 yield 语句左侧还未执行,
无法赋值所以必须是 send(None). 而后 send(‘send 1’) 调用。
send 函数中的参数 send_1 被赋值给 value. 生成器函数继续执行。
一直到下一次执行 yield 语句。

而 close 函数执行时,会自动执行生成器函数中的 finally 部分代码。

throw 函数 会在生成器函数暂停位置引发 throw 参数中传递的异常。
如果有捕获该异常则正常执行,没有则关闭生成器,并传播给调用者。
总之,这三个函数是用于控制生成器函数的执行。
最后我们做个总结:

  • 1.生成器是特殊的迭代器
  • 2.生成器可以由生成器函数产生
  • 3.生成器用于控制生成器函数的执行

练习:想想在什么场景下可以使用生成器优化代码呢。留下你的代码在评论吧。
当然也欢迎扫一扫关注我的微信公众号。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值