跳转至

Python的生成器(Generator)

通过列表生成式可以直接创建一个列表,但是,列表生成式受到内存限制,因为列表容量肯定是有 限的。如果创建一个包含100万个元素的列表,那么这将会占用很大的存储空间。若仅仅只访问前面几个元素,则后面绝大多数元素占用的空间都浪费了。所以,如果列表元素可以按照某种算法推算出来, 那就可以在循环的过程中不断推算出后续的元素。这样就不必创建完整的list,从而节省大量的空间。在 Python中,这种一边循环一边计算的机制,被称为生成器(Generator)。生成器是实现迭代器的一种机制。其功能的实现依赖于yield表达式,除此之外它跟普通的函数没有两样。

简单生成器

要创建一个Generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[ ]改成( ),就创建了一个Generator:

>>> L = [x * x fbr x in range(10)]
>>> g = (x * x fbr x in range(10))
>>>
>>> print(L)
[0,1,4,9,16,25,36,49,64,81]
>>> print(g)
<generator object <genexpr> at 0x03B54600>

在 Python 3 中:

>>> g = (x * x for x in range。))
>>> print(g.next())
Traceback (most recent call last):
File '<stdin>', line 1, in <module>
AttributeError: 'generator* object has no attribute 'next*

>>> print(g.__next__())
0
>>> print(g.__next__())
1
>>> print(next(g))    #这里*2*种写法都可以
4
>>> print(g.__next__())
Traceback (most recent call last):
File '<stdin>', line 1, in <module>
Stopiteration
>>>

Generator保存的是算法,每次调用next(),就可以计算出下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出Stopiteration的错误。当然,上面这种不断调用next()。方法不推荐使用,正确的方法是使用for循环,因为Generator也是可迭代对象

g=(x * x for x in range(3))
for n in g:
print(n)

yield语句的生成器

如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个Generator。 与普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,可以简单理解为:生成器 就是一个迭代器。在调用生成器运行的过程中,每次遇到yield时函数会暂停并保存当前所有的运行信息, 返回yield的值,并在下一次执行next。方法时从当前位置继续运行。调用一个生成器函数,返回的是一 个迭代器对象。

range功能:

range(start, stop[, step])

参数说明:

  • start: 计数从 start 开始。默认是从 0 开始。例如range(5)等价于range(0, 5);
  • stop: 计数到 stop 结束,但不包括 stop。例如:range(0, 5) 是[0, 1, 2, 3, 4]没有5
  • step:步长,默认为1。例如:range(0, 5) 等价于 range(0, 5, 1)

例如:

for i in range(3,-1,-1):
    print(i)

运行结果:

3
2
1
0

生成器

def reverse(data):
    for index in range(len(data)-1, -1, -1):
        yield data[index]

>>>

>>> for char in reverse('golf'):
...     print(char)
...
f
l
o
g