zoukankan      html  css  js  c++  java
  • 生成器(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

  • 相关阅读:
    oracle中 connect by prior 递归算法
    sql优化__rownum的使用【转】
    ASP.NET Core四大部件
    .net core Socket
    .NET Core 配置文件
    .NET Core IOC AOP
    Quartz.Net—MisFire
    Quartz.Net—配置化
    Quartz.Net—IJob特性
    Quartz.Net—DateBuilder
  • 原文地址:https://www.cnblogs.com/dreamer-fish/p/5426893.html
Copyright © 2011-2022 走看看