再谈python生成器Generator(二)

最近在读《流畅的python》,读书的好处是它可以帮你把混乱的概念屡清楚。这篇文章再谈几个概念:生成器、生成器函数、生成器表达式。

生成器是一个对象,是一个实例化的东西,等同于迭代器。

生成器函数是个函数,函数体含有yield表达式。

>>> def gen_123():
...     yield 1
...     yield 2
...     yield 3
...
>>> gen_123
<function gen_123 at 0x0243D570>
>>> gen_123()
<generator object gen_123 at 0x02424A08>

从生成器函数可以得到一个生成器,而根据上一篇文章,生成器就是一个迭代器,不断的应用next()能遍历每一个元素,最终得到StopIteration异常。遍历出来的元素就是生成器函数里面yield的内容。

那什么是生成器表达式呢?

书中是从列表推导引出这个概念的,并介绍了“惰性实现”的概念。

下面是书中14-8的例子

>>> def gen_AB(): #①
...     print('start')
...     yield 'A'
...     print('continue')
...     yield 'B'
...     print('end.')
...
>>> res1 = [x*3 for x in gen_AB()] #②
start
continue
end.
>>> for i in res1: #③
...     print('-->',i)
...
('-->', 'AAA')
('-->', 'BBB')
>>> res2 = (x*3 for x in gen_AB()) #④
>>> res2 #⑤
<generator object <genexpr> at 0x02264AA8>
>>> for i in res2: #⑥
...     print('-->',i)
...
start
('-->', 'AAA')
continue
('-->', 'BBB')
end.
>>>
res1是列表推导的结果,列表推导迫不及待地把生成器gen_AB()先遍历了,所以输出了start、congtinue和end,得到的结果res1是一个list对象。

res2是生成器表达式的结果,生成器表达式仅输出生成器,不遍历生成器。这就是“惰性”的意思,把遍历操作留给程序员,就是⑥那里的for循环。

其实生成器表达式和生成器函数都是为了得到生成器,只不过使用生成器表达式可以省去写生成器函数!

那么何时使用生成器函数,何时使用生成器表达式呢?

作者在14.7节给出了答案,直接引用过来:

遇到简单的情况时,可以使用生成器表达式,因为这样扫一眼就知道代码的作用。

根据我的经验,选择使用哪种句法很容易判断:如果生成器表达式要分成很多行写,我倾向于定义生成器函数,以便提高可读性。此外,生成器函数有名称,可以重复使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值