python生成器的深入理解,与协程的关系,send的理解

本文深入探讨Python生成器,包括两种形式:列表生成式和带yield的函数。协程作为生成器的支持,能够实现单线程内的异步IO操作,避免传统多线程的IO阻塞问题。通过实例解析了如何使用send()进行协程间的通信,并介绍了使用协程实现的生产者-消费者模型。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们知道生成器有两种形式:

1.(x for _ in range(10))也就是列表生成式改成( )而不是[ ]

2.用了yield的函数

协程是什么:协程又称微线程,纤程,python中协程是通过生成器来支持的

子程序或者称为函数,子程序的互相调用会形成调用栈,需要一层层返回,子程序是默认return None的,也就是返回了函数就结束了,下次执行又是从头开始------>子程序是协程的一种特例

协程有什么好处:协程可以实现用一个线程来进行异步IO,也就是说不像函数那样,一个线程执行一个函数,当一个线程因为IO阻塞时,需要进行切换线程才能实现异步的效果

我们传统的生产者-消费者模型是通过多线程来实现的,一个线程写,一个线程读,通过线程获得锁防止数据的不一致性

但是如果用协程来实现,同一个线程内,一个函数写完,yield出来给另一个函数读,读完在通过send()再次进入写函数进行上次的后续执行

例子:

    def Gene():         #生成器函数
        print("ok")
        x = 100         
        print(x)
        first = yield 50    #这里就是send函数的关键
        # send所传递的值其实就是给 =号左边的左值赋值
        print(first)
    
        second = yield x  # 这里试第二个断点
        print(second)
    
        z = 'third' 
        third = yield z
        print(third)
     
     
    inst = Gene()                   #创建生成器对象,并没有启动,也就是没有执行进去
    output1 = inst.send(None)       #启动生成器,运行到第一个yield
    print(output1)                 #这边的output1获得的是yield的返回值 50
    output2 = inst.send(30)
    print(output2)
    output3 = inst.send(None)

#执行结果:
# ok
# 100
# 50
# 30
# 100
# None

这个代码关键是要看懂xx=yield xx,和send(xx)

我们需要知道:一开始inst.send(None)是用来启动生成器的,也就是执行进去,然后print("ok"),print(x),然后执行到yield 50把50给抛出来赋值给了output1,然后print(output1),然后又通过inst.send(30)进入到生成器上次执行的后续,yield 50已经执行过了,接下来就是send(30)赋值给first,然后print(first),然后yeild x也就是抛出了100,给output2接收,print(output2),在send(None)再次进入上次执行的后续,也就是second被赋值None,然后print(second),一直执行到yield z也就是抛出‘third’,然后就没有后续了。即便我们没有关闭生成器---->inst.close()

可以看出这里面已经又涉及到类似函数调用了,只需要通过send()就可以返回到上次执行的后续

我们可以看出,xx=yield yy是先抛出yy,再把其他地方send的东西赋值给xx

注意:这里的最开始的send(None)仅用于启动生成器,当然我们也可以用next(Gene)来启动生成器

下面我们来写一下生产者-消费者的协程实现:

# 消费者
def consumer():
    response = None
    while True:
        item = yield response
        if not item:
            return None
        print('consumer is consume {0}'.format(item))
        response = 'consume done'

# 生产者
def producer(con):
    con.send(None)
    n = 0
    for i in range(1, 13):
        n += 1
        print('producer have prodeced {0}'.format(i))
        result = con.send(n)
        print('consumer return {0}'.format(result))
    con.close()# 关闭生成器

con = consumer()
producer(con)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值