python3:生成器

一.简单生成器特性

查询了官方文档(见参考资料[1]),主要有以下几个概念:

generator:

返回一个 generator iterator 的函数。它看上去很像普通的函数,只是它包含 yield 表达式用于生成一系列的值,这些值可以用于 for 循环或通过next() 函数一次一个地取出来。

通常是指一个 generator 函数,但在某些上下文中可能是指一个 generator iterator。如果意欲达到的含义不明确,则使用完整术语可避免含糊不清。(注:即我们常说的生成器函数)

generator iterator:

由一个 generator 函数创建的对象。

每个 yield 临时挂起当前的运行,记住执行的位置和状态(包括局部变量和等待的 try 语句)。当 generator iterator 恢复时,它从离开的位置重新开始(与函数不同,函数每次调用从起始开始)。(注:我们常说的生成器对象)

generator expression:

一个返回 iterator 的表达式。它看起来像一个普通的表达式后跟一个定义循环变量的for表达式、range和一个可选的if表达式。这个组合表达式为闭包函数生成值(注:我们常说的生成器表达式):

>>> sum(i*i for i in range(10))         # sum of squares 0, 1, 4, ... 81
285

解释:

挂起,返回出中间值,并多次继续的协同程序成为生成器(从语法上讲,生成器是一个带yield关键字的函数)。与迭代器的—__next__()似,迭代器使用yield关键字,当遇到yield关键字时,先返回一个值给调用者,然后“暂停”代码的执行。当被生成器的next()方法调用时,它会准确的从离开的地方继续,如果没有值可以访问,那么就会抛出StopIteration——由于Python的for 循环有next()调用和对StopIteration处理,所以使用for循环而不是手动调用生成器更优雅一些。

# -*- coding:utf-8 -*-
from collections.abc import Iterator


def my_generator():
    yield 1
    yield 2


mg = my_generator()
print(mg)   # 生成器函数返回一个生成器对象: <generator object my_generator at 0x00000225C64BC480>

# 可以使用next()调用生成器,但是会引发StopIteration异常
# print(next(mg))  # 1
# print(next(mg))  # 2
# print(next(mg))  # StopIteration

# 使用for循环比较优雅,自动处理StopIteration
for i in mg:
    print(i)    # 1 2

列表解析生成一个list,同时暂用内存。而生成器表达式返回一个迭代器,采用的时延迟计算,占用内存更小。

二.加强的生成器特性

生成器除了可使用next()获取下一个值,还可以将值返回给生成器[send()],在生成器中抛出异常[throw()],以及要生成器退出[close()]。

>>> def counter(start_at=0):
...     count = start_at
...     while True:
...         val = (yield count)
...         if val is not None:
...             count = val
...         else:
...             count += 1
...
>>> count = counter(5)
>>> next(count)
5
>>> count.send(9)
9
>>> next(count)
10
>>> count.close()
>>> next(count)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>>

三.总结

总结引用kissg.me博客的内容,见参考资料[2]。

iterable-iterator-generator

  1. 可迭代对象(Iterable)是实现了__iter__()方法的对象,通过调用iter()方法可以获得一个迭代器(Iterator)

  2. 迭代器(Iterator)是实现了__iter__()__next__()的对象

  3. for ... in ...的迭代,实际是将可迭代对象转换成迭代器,再重复调用next()方法实现的

  4. 生成器(generator)是一个特殊的迭代器,它的实现更简单优雅.

  5. yield是生成器实现__next__()方法的关键.它作为生成器执行的暂停恢复点,可以对yield表达式进行赋值,也可以将yield表达式的值返回.

四.参考资料

[1]python官方文档generator:https://docs.python.org/3/glossary.html#term-generator

[2]Python之生成器详解:http://kissg.me/2016/04/09/python-generator-yield/#generator

[3]Python官方文档Generator-iterator methods:https://docs.python.org/3/reference/expressions.html#generator-iterator-methods

[4]yield表达式:https://docs.python.org/3/reference/expressions.html#yield-expressions

猜你喜欢

转载自blog.csdn.net/cckavin/article/details/86361943