返回介绍

14.6 Sentence 类第5版:生成器表达式

发布于 2024-02-05 21:59:47 字数 1883 浏览 0 评论 0 收藏 0

简单的生成器函数,如前面的 Sentence 类中使用的那个(见示例 14-7),可以替换成生成器表达式。

生成器表达式可以理解为列表推导的惰性版本:不会迫切地构建列表,而是返回一个生成器,按需惰性生成元素。也就是说,如果列表推导是制造列表的工厂,那么生成器表达式就是制造生成器的工厂。

示例 14-8 演示了一个简单的生成器表达式,并且与列表推导做了对比。

示例 14-8 先在列表推导中使用 gen_AB 生成器函数,然后在生成器表达式中使用

>>> 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 0x10063c240>
>>> for i in res2:  # ➏
...   print('-->', i)
...
start
--> AAA
continue
--> BBB
end.

❶ gen_AB 函数与示例 14-6 中的一样。

❷ 列表推导迫切地迭代 gen_AB() 函数生成的生成器对象产出的元素:'A' 和 'B'。注意,下面的输出是 start、continue 和 end.。

❸ 这个 for 循环迭代列表推导生成的 res1 列表。

❹ 把生成器表达式返回的值赋值给 res2。只需调用 gen_AB() 函数,虽然调用时会返回一个生成器,但是这里并不使用。

❺ res2 是一个生成器对象。

❻ 只有 for 循环迭代 res2 时,gen_AB 函数的定义体才会真正执行。for 循环每次迭代时会隐式调用 next(res2),前进到 gen_AB 函数中的下一个 yield 语句。注意,gen_AB 函数的输出与 for 循环中 print 函数的输出夹杂在一起。

可以看出,生成器表达式会产出生成器,因此可以使用生成器表达式进一步减少 Sentence 类的代码,如示例 14-9 所示。

示例 14-9 sentence_genexp.py:使用生成器表达式实现 Sentence 类

import re
import reprlib

RE_WORD = re.compile('\w+')


class Sentence:

  def __init__(self, text):
    self.text = text

  def __repr__(self):
    return 'Sentence(%s)' % reprlib.repr(self.text)

  def __iter__(self):
    return (match.group() for match in RE_WORD.finditer(self.text))

与示例 14-7 唯一的区别是 __iter__ 方法,这里不是生成器函数了(没有 yield),而是使用生成器表达式构建生成器,然后将其返回。不过,最终的效果一样:调用 __iter__ 方法会得到一个生成器对象。

生成器表达式是语法糖:完全可以替换成生成器函数,不过有时使用生成器表达式更便利。下一节说明生成器表达式的用途。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文