zoukankan      html  css  js  c++  java
  • python yield 和 yield from用法总结

    #例1. 简单输出斐波那契數列前 N 个数
    #缺点:该函数可复用性较差,因为 fab 函数返回 None,其他函数无法获得该函数生成的数列
    #要提高 fab 函数的可复用性,最好不要直接打印出数列,而是返回一个 List。
    def fab1(max):
        n, a, b = 0, 0, 1
        while n < max:
            print(b,end=' ')
            a, b = b, a + b
            n = n + 1
    fab1(5)  

    #例 2.
    #缺点:该函数在运行中占用的内存会随着参数 max 的增大而增大,如果要控制内存占用,
    #最好不要用 List 来保存中间结果,而是通过 iterable 对象来迭代  
    def fab2(max):
        n, a, b = 0, 0, 1
        L = []
        while n < max:
            L.append(b)
            a, b = b, a + b
            n = n + 1
        return L

    #例3
    #说明:带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,
    #调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!
    #在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,
    #下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,
    #于是函数继续执行,直到再次遇到 yield。
    def fab3(max):
        n, a, b = 0, 0, 1
        while n < max:
            yield b
            # print b
            a, b = b, a + b
            n = n + 1
    f=fab3(5)
    print("f是一个可迭代对象,并没有执行函数")
    print(f)
    print('fab3返回的是一个iterable 对象,可以用for循环获取值')
    for n in f:
        print(n)

    #例4:
    #说明:yield from iterable本质上等于for item in iterable: yield item的缩写版    
    
    def f_wrapper1(f):
        for g  in f:
            yield g
    wrap = f_wrapper1(fab3(5))
    for i in wrap:
        print(i,end=' ')
    
    print('
    使用yield from代替for循环')
    def f_wrapper2(f):
         yield from f#注意此处必须是一个可生成对象
    wrap = f_wrapper2(fab3(5))
    for i in wrap:
        print(i,end=' ')
    print('
    ---------------------')
    
    
    print('yield from包含多个子程序')
    def g(x):
        yield from range(x, 0, -1)
        yield from range(x)
    print(list(g(5)))
    for g  in g(6):
        print(g,end=',')
        
        
    print('
    ---------------------')  
    注意红色部分就是替代的部分,yield from iterable本质上等于for item in iterable: yield item的缩写版   

    #例5 利用yield from语句向生成器(协程)传送数据 
    #传统的生产者-消费者模型是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁。
    #如果改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,换回生产者继续生产,效率极高:
    def  consumer_work(len):
        # 读取send传进的数据,并模拟进行处理数据
        print("writer:")
        w=''
        while True:
            w = yield w    # w接收send传进的数据,同时也是返回的数据
            print('[CONSUMER] Consuming %s...>> ', w)
            w*=len #将返回的数据乘以100
            time.sleep(0.1)  
    def consumer(coro):
        yield from coro#将数据传递到协程(生成器)对象中
    
    
    def produce(c):
        c.send(None)# "prime" the coroutine
        for i in range(5):
            print('[Produce] Producing %s----', i)
            w=c.send(i)#发送完成后进入协程中执行
            print('[Produce] receive %s----', w)
        c.close()
        
    c1=consumer_work(100)
    produce(consumer(c1))

    执行结果:
    writer:
    [Produce] Producing %s---- 0
    [CONSUMER] Consuming %s...>>  0
    [Produce] receive %s---- 0
    [Produce] Producing %s---- 1
    [CONSUMER] Consuming %s...>>  1
    [Produce] receive %s---- 100
    [Produce] Producing %s---- 2
    [CONSUMER] Consuming %s...>>  2
    [Produce] receive %s---- 200
    [Produce] Producing %s---- 3
    [CONSUMER] Consuming %s...>>  3
    [Produce] receive %s---- 300
    [Produce] Producing %s---- 4
    [CONSUMER] Consuming %s...>>  4
    [Produce] receive %s---- 400

    yield from一般掌握这两种用法即可;
  • 相关阅读:
    176. Second Highest Salary
    175. Combine Two Tables
    172. Factorial Trailing Zeroes
    171. Excel Sheet Column Number
    169. Majority Element
    168. Excel Sheet Column Title
    167. Two Sum II
    160. Intersection of Two Linked Lists
    个人博客记录
    <meta>标签
  • 原文地址:https://www.cnblogs.com/cdma/p/6839640.html
Copyright © 2011-2022 走看看