生成器(generator),迭代器(yield)
g=(i for i in range(10)) #小括号表示生成一个迭代生成器。[]是列表生成器 g.__next__()
yield将一个函数变成生成器
import time def f(): for i in range(10): yield i #如果换成return i,则最终只能返回0。 print('aa') m=f() #m是一个generator print(m) print(dir(m)) print(m.__next__()) print(m.__next__()) time.sleep(2) print(m.__next__())
按字节读取文本:
def rb(): f=open('e:\\a.txt','rb') while True: size=6 #每次读取6个字节 block=f.read(size) if block: yield block else: break f.close() rr=rb() for r in rr: print r
yield中的next()和send():
def yed(): print "enter fun", yield 10 yy = yed() yy.next() #返回"enter fun"
print yy.next() #返回 enter fun 10
def yed(): print "enter fun", yield 10 print "next1" yield 20 yy = yed() yy.next() yy.next() # #返回enter fun next1 def yed(): print "enter fun", yield 10 print "next1" yield 20 yy = yed() yy.next() yy.send('hello') #此处send的参数hello被yield 10接收了,但是并没有进行打印,所以不会被打印 #返回enter fun next1 def yed(): print "enter fun", y1 = yield 10 print "next1", print y1 yield 20 yy = yed() yy.next() yy.send('hello') #send发送的值会成为当前yield的结果,即yield 10,即y1,并且send的返回结果是下一个yield的结果(相当于了next()) #返回 enter fun next1 hello def yed(): print "enter fun", y1 = yield 10 print "next1", print y1 y2 = yield 20 yy = yed() mn = yy.next() #结果为yield 10的参数,即10 ms = yy.send('hello') #结果为yield 20的参数,即20。hello被y1接收到了 print 'mn: %s, ms: %s' %(mn,ms) #返回enter fun next1 hello #mn: 10, ms: 20
第一次调用时,要使用next()语句或是send(None),不能使用send发送一个非None的值,否则会出错的,因为没有yield语句来接收这个值。所以第一次时next() == send(None)
send(msg) 和 next()是有返回值的,它们的返回值很特殊,返回的是下一个yield表达式的参数。比如yield 10,则返回10 。
协同处理数据:http://www.tuicool.com/articles/VBfAzaQ
我们现在利用yield关键字会自动冻结函数堆栈的特性,想象一下,假如现在有两个函数f1()和f2(),各自包含yield语句,见下例。主线程先启动f1(), 当f1()执行到yield的时候,暂时返回。这时主线程可以将执行权交给f2(),执行到f2()的yield后,可以再将执行权交给f1(),从而实现了在同一线程中交错执行f1()和f2()。f1()与f2()就是协同执行的程序,故名协程。
import random #消费生成的数据 def consume(): print 'waiting to consume' while True: data = yield sum_data = sum(data) print '%s was consumed,the sum is %d ' %(str(data),sum_data) #生成数据 def produce(): print 'begin to produce' consumer = consume() consumer.next() while True: data = random.sample(range(10),3) print '%s produced' %(str(data)) consumer.send(data) yield producer = produce() for i in range(5): producer.next() #直接执行produce()里面的代码:在produce里面先生成data,然后再将其发送给consume
可以优化为如下:
import random #消费生成的数据 def consume(): print 'waiting to consume' while True: data = yield sum_data = sum(data) print '%s was consumed,the sum is %d ' %(str(data),sum_data) #生成数据 def produce(consumer): print 'begin to produce' while True: data = random.sample(range(10),3) print '%s produced' %(str(data)) consumer.send(data) yield consumer = consume() producer = produce(consumer) consumer.next() #打印waiting to consum for i in range(5): producer.next() #直接执行produce()里面的代码:在produce里面先生成data,然后再将其发送给consume
返回结果如下:
waiting to consume begin to produce [2, 9, 3] produced [2, 9, 3] was consumed,the sum is 14 [1, 5, 2] produced [1, 5, 2] was consumed,the sum is 8 [8, 5, 4] produced [8, 5, 4] was consumed,the sum is 17 [6, 1, 2] produced [6, 1, 2] was consumed,the sum is 9 [8, 6, 3] produced [8, 6, 3] was consumed,the sum is 17
异步并发????
from time import sleep,ctime def consumer(name): print '%s want to consume' % name while True: bb = yield print '%s was consumed by %s' %(bb,name) def producer(pname): c1=consumer('A') c2=consumer('B') c1.next() c2.next() print '%s begin to produce' % pname for i in range(5): sleep(1) print '%s produce 2' % pname c1.send(i) c2.send(i) producer('zhangsan')
返回结果如下:
A want to consume B want to consume zhangsan begin to produce zhangsan produce 2 0 was consumed by A 0 was consumed by B zhangsan produce 2 1 was consumed by A 1 was consumed by B zhangsan produce 2 2 was consumed by A 2 was consumed by B zhangsan produce 2 3 was consumed by A 3 was consumed by B zhangsan produce 2 4 was consumed by A 4 was consumed by B
继续看这个-2016.5.3 http://my.oschina.net/u/877348/blog/184058