关于生成器(在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 "<input>", 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 "<input>", line 1, in <module> File "<input>", line 4, in sum ValueError: Memada!!!