巧妙使用语法实现生成器内层yield值传递

引言:
  • 笔者最近在学习协程和yield使用的相关知识和案例的情况下, 发现了yield from在python2里面是不支持的, 所以所看的论文上的yield from的使用方法在python2里面根本跑不起来.
  • 这里面无法复用原代码的让我很纠结的原因就是 迭代器函数调用send({value})这个方法的时候如果是多个yield迭代的情况下, 没办法正常的将send里面的值传递过去, 所以有了以下的一个粗暴实现…
# 子生成器
def average_gen():
    total = 0
    count = 0
    average = 0
    while True:
        new_num = yield average
        count += 1
        total += new_num
        average = total/count

# 委托生成器
def proxy_gen():
    x = average_gen()
    # 方法一: 使用计数器, 正常情况下第一次预激活的时候m是没有被定义的, 通过次数来判断
    c = 0
    while True:
        m = yield x.send(m if c else None)
        c += 1
    # 方法二: 直接try catch来检查
        try:
            m = yield x.send(m)
        except UnboundLocalError:
            m = yield x.send(None)

# 调用方
def main():
    calc_average = proxy_gen()
    calc_average.send(None)          # 预激下生成器
    print "放飞自我"
    print calc_average.send(10)  # 打印:10.0
    print calc_average.send(20)  # 打印:15.0
    print calc_average.send(30)  # 打印:20.0
    calc_average.close() # 关闭协程,如果不关闭, 则该协程将一直挂起

if __name__ == '__main__':
    main()

两种方式的生产者消费者模型

传统的
import time
import random
from multiprocessing import Queue, Process


def consumer(name, q):
    while True:
        res = q.get()
        time.sleep(random.randint(1, 3))
        print('消费者》》%s 准备开吃%s。' % (name, res))


def producer(name, q):
    i = 0
    while 1:
        time.sleep(random.randint(1, 2))
        i += 1
        res = '大虾%s' % i
        q.put(res)
        print('生产者》》》%s 生产了%s' % (name, res))


if __name__ == '__main__':
    q = Queue()  # 一个队列

    p1 = Process(target=producer, args=('monicx', q))
    c1 = Process(target=consumer, args=('lili', q))

    p1.start()
    c1.start()
先科普点小知识

Python multiprocessing.Queue 和 Queue区别

  • Queue是python自带的标准库,支持线程安全,所以多线程下可以随意使用,不会出现写冲突。
  • multiprocessing.Queue这个multiprocessing模块封装的,它支持多进程之间的交互,比如master-worker模式下,master进程写入,work进程消费的模式,支持进程之间的通信。也就是进程安全
  • 无论是线程安全还是进程安全, 都是内部通过加锁实现的, 即会损失一些性能.
协程

缺点:感觉这种方式去实现耦合的太紧了.

def consumer(name, producer):
    while True:
        res = next(producer)
        print('消费者》》%s 准备开吃%s。' % (name, res))


def producer(name):
    i = 0
    while 1:
        i += 1
        res = '大虾%s' % i
        print('生产者》》》%s 生产了%s' % (name, res))
        yield i


if __name__ == '__main__':
    producer = producer('lily')
    consumer('didi', producer)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值