生成器

一、什么是生成

生成器是一种用普通的函数语法定义的迭代器。

什么是Python式的生成器?从语法上讲,生成器是一个带yield语句的函数。

一个函数或者子程序只返回一次,但一个生成器能暂停执行并返回一个中间的结果——那就是yield语句的功能,返回一个值给调用者并暂停执行。

当生成器的next()方法被调用的时候,他会准确的从离开的地方继续。

生成器不会把结果保存在一个系列中,而是保存生成器的状态,在每次进行迭代时返回一个值,直到遇到StopIteration异常结束。

生成器表达式能做的事情列表解析基本都能处理,只不过需要处理的序列比较大时,列表解析比较费内存。

生成器函数:在函数中如果出现了yield关键字,那么该函数就不再时普通函数,而是生成器函数。

但是生成器函数可以产生一个无线的序列,这样列表根本没有办法进行处理。

yield的作用就是把一个函数变成一个generator,带有yield的函数不再是一个普通函数。python解释器会将其视为一个generator。

如果要打印一列数,用函数这样写:

def fibs(num):
    result = [0,1]
    for i in range(num-2):
        result.append(result[-2]+result[-1])
    return result
print(fibs(10))
执行结果:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

函数只能返回一次,所以必须返回一个阵列。如果换成生成器,就可以一次返回一个值,不断返回多次。如果使用生成,它就会不断地调用生成器对象的next()方法。

 二、创建一个简单的生成器

#使用生成器打印表中所有的值。
def flatten(nested):
    for sublist in nested:
        for element in sublist:
            yield element

nested = [[1,2,3],[4,5],(6,7)]
for num in flatten(nested):
    print(num)

#执行结果
1
2
3
4
5
6
7

如果用列表解析也能实现:

for m in nested:
    for n in m:
        print(n)

如果是多层,该如何实现了?——递归生成器

 

三、递归生成器

上面所讲述的生成器可以处理多层嵌套。如何处理任意层嵌套了?

def flatten(nested):
    try:
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield  nested

nested = [[1,2],[[11],3,4,(8,9,10),5]]

for i in flatten(nested):
    print(i)

当flatten被调用时,有两种可能性:基本情况和需要递归的情况。在基本的情况中,函数被告知展开一个元素(比如一个数字),这种情况下,for循环会引发一个TypeError异常,因为试图对一个数字进行迭代,生成器会产生一个元素。如果展开的是一个列表(或者其它可迭代对象),那么就要进行特殊处理。程序必须便利所有的子列表(可能不是列表),并对调用flatten。然后使用另一个for循环来产生被展开的子列表中的所有元素。

def flatten(nested):
    try:
        try:nested + ''
        except TypeError:pass
        else: raise TypeError
        for sublist in nested:
            for element in flatten(sublist):
                yield element
    except TypeError:
        yield nested

print(list(flatten(['foo',['bar',['baz','1','2']]])))

 

四、通用生成器

生成器是一个包含yield关键字的函数。当它被调用时,在函数体中的代码不会被执行,而是返回一个迭代器。

每次请求一个值,就会执行生成器中的代码,直到遇到一个yield或者return语句,yield语句意味着应该生成一个值,return语句意味着生成器要停止执行。

生成器是由两部分组成:生成器的函数和生成器的迭代器。生成器的函数是用def语句定义的,包含yield的部分,生成器的迭代器是这个函数返回的部分。

posted @ 2017-11-04 21:41  明王不动心  阅读(138)  评论(0编辑  收藏  举报