python:生成器

生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,会占用很大的存储空间,若仅需要访问前面一部分元素,那么绝大多数元素所占空间就白白浪费了

所以,如果列表元素可以按照某种算法推出,那么就不必创建完整的list,从而节省大量空间。在python中,这种机制为迭代器:generator

生成器只有在调用时才会生成相应的数据,它只记录当前位置,只有一个__next__()方法取得下一个数据(python2为next()方法)。而列表在没有调用它的情况下依然会生成数据.

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

L = [x*x for x in range(10)] #列表生成式

g = (x*x for x in range(10)) #生成器

所以,我们创建了一个generator后,基本上不会调用__next__()方法,而是通过for 循环来迭代它

for i in g:

  print i

generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

比如,著名的菲波那契数列(Fibonacci),出第一个和第二个数外,任意一个数都可由前两个数相加得到:

#!usr/bin/env python
# -*- coding:utf-8 -*-

__author__ = "Samson"

def fib(max):
n,a,b = 0,0,1#注意,该句相当于t = (0,0,1),n=t[0],a=t[1],b=t[2]
while n < max:
print(b)
yield b#只要有yield存在,便是一个生成器
a,b = b,a+b
n+=1
return "done"
f = fib(100)
print(f.__next__())

还可以通过yield实现在单线程的情况下实现并发运算的效果,如:
#!usr/bin/env python
# -*- coding:utf-8 -*-

__author__ = "Samson"

import time
def consumer(name):
print("%s 准备吃饺子啦!" %name)
while True:
jiaozi = yield#保存当前状态并返回

print("饺子[%s]来了,被[%s]吃了!" %(jiaozi,name))


c = consumer("lixiang")
c.__next__()
# b1 = "韭菜馅"
# c.send(b1)#调用yield的同时给jiaozi传值
# #c.__next__()
def producer(name):
c = consumer("A")#把函数变成生成器赋给c,里面还没执行
c2 = consumer("B")
c.__next__()
c2.__next__()
print("老子开始准备做饺子了")
for i in range(10):
time.sleep(1)
print("做了1个饺子,分两半!")
c.send(i)
c2.send(i)
producer("samson")
原文地址:https://www.cnblogs.com/cansun/p/8099892.html