Python拾遗之迭代器和生成器(二)

迭代器与生成器(二)


关于生成器(在Python中)

生成器可以称为特殊的迭代器,因为它具有可迭代的属性,也具备next方法,而它的特殊之处在于其具有协同程序的概念,从语法上讲,生成器是一个带yield语句的函数,从而保证生成器能暂停执行,返回中间的结果(这也是yield语句的功能,即返回一个只给调用者并暂停执行),当生成器的next方法被再次调用时,它会准确的从离开的地方继续执行。例如,通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含特别多元素的列表,不仅占用很大的存储空间,而且如果仅仅需要访问几个元素,那绝大多数元素占用的空间都浪费了。但是,如果列表元素可以按照某种算法推算出来,在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。据上述,这种一边循环一边计算的机制,并且具有上所述的挂起返回中间值并且多次继续的协同程序,谓之生成器(Generator)


关于协同程序

可以运行的独立函数调用,可以暂停或者挂起,同时保存现场,并从程序离开的地方重新开始。依靠挂起,完成cpu或者IO的切换,达到协程的意义。


构建生成器对象:

实例一:(调用生成器函数,获得一个生成器对象)

def simple_gen():
        yield 1
        yield 2
gen_obj = simple_gen()
print type(gen_obj)

运行结果:

<type 'generator'>

实例二:(把一个列表生成式的[]改成(),就创建了一个generator)

li = [i * i for i in range(10)]
print type(li)
gen = (i * i for i in range(10))
print type(gen)

运行结果:

<type 'list'>
<type 'generator'>

如何使用生成器

实例三:(手动迭代,当生成器对象无值返回时,一个StopIteration将会抛出)


>>> gen = (i * i for i in range(3))
>>> gen.next()
0
>>> gen.next()
1
>>> gen.next()
4
>>> gen.next()
Traceback (most recent call last):
  File "", line 1, in <module>
StopIteration

实例四:(python的for循环有next()调用和对StopIteration的处理)

gen = (i * i for i in range(3))
for i in gen:
    print i

运行结果:

0
1
4

实例五:(利用send方法将值送给生成器,调用close方法,让生成器抛出异常)


>>> def sum(start=0):
    num = start
while True:
#保证send()回来的数据值得到接收
        var = (yield num)
        if var is not None:
            num = var
        else:
            num += 1
>>> t = sum(2)
>>> t.next()
2
>>> t.next()
3
>>> t.next()
4
>>> t.send(7)
7
>>> t.send(9)
9
>>> 
>>> t.close()
>>> t.next()

实例六:(throw方法允许客户传入要抛出的任何类型的异常)

>>> def sum(start=0):
    num = start
    while True:
        var = (yield num)
        if var is not None:
            num = var
        else:
            num += 1
>>> s = sum(1)
>>> s.next()
1
>>> s.next()
2
>>> s.throw(ValueError('Memada!!!'))   
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 4, in sum
ValueError: Memada!!!

你可能感兴趣的:(Python开发,python高级编程)