【python 生成器 面试必备】yield关键字,协程必知必会系列文章--自己控制程序调度,体验做上帝的感觉 2

这篇文章要解决的问题:How to Pass Value to Generators Using the "yield" Expression in Python

ref:https://python.plainenglish.io/yield-python-part-ii-e93abb619a16

1.如何传值

yield 是一个表达式!!!!

yield is an expression! It is used just like an expression would:

received = yield 'hello'

In this case value of received is hello .

received = yield

Here, the value of received is None .

However, it's been suggested to use the expression form sparingly also because of confusion.

但是也有人建议少用,因为容易引起混淆!

2.yield 生成器的几种状态

···python

from inspect import getgeneratorstate

复制代码
def gen_echo():
    while True:
        received = yield
        print(f'Inside method: {getgeneratorstate(echo)}')
        print(f'You said: {received}')


echo = gen_echo()
print(f'After generator creation: {getgeneratorstate(echo)}')
print(f'First call value to generator: {next(echo)}')
print(f'After first call to generator: {getgeneratorstate(echo)}')

# sending value to generator
echo.send('hello')

print(f'After sending the value: {getgeneratorstate(echo)}')

···

bash 复制代码
C:\Users\HP\.conda\envs\torch1.8\python.exe D:/code/python_project/01-coroutine-py-mooc/8/demo_ccc.py
After generator creation: GEN_CREATED
First call value to generator: None
After first call to generator: GEN_SUSPENDED
Inside method: GEN_RUNNING
You said: hello
After sending the value: GEN_SUSPENDED

3.原理图

其实就是线程【用户级线程=也叫协程】的状态转换图!!!

3.协程练习

3.1 原始方式

python 复制代码
def running_averager():
    total = 0
    count = 0
    running_average = None
    while True:
        value = yield running_average
        total += value
        count += 1
        running_average = total/count

averager = running_averager() # generator creation
next(averager) # priming
print(averager.send(10))
print(averager.send(20))
print(averager.send(30))

3.2 闭包【装饰器】方式

3.1相同的功能代码再用闭包的方式实现一遍,After priming, the generator is on suspend state, after which we can send data to a generator and get running_average.

Since we have to do that extra step of next() to generator, why not have it automated. We have a decorator to do that.

python 复制代码
def prime(generator_fun):
    '''
    Method to prime generator function
    '''
    generator = generator_fun()
    next(generator)
    return generator

def running_averager():
    '''
    calculates average of values sent
    '''
    total = 0
    count = 0
    running_average = None
    while True:
        value = yield running_average
        total += value
        count += 1
        running_average = total/count

iterable = [10, 11, 12, 13, 14, 15]
averager = prime(running_averager) # decorating

for value in iterable:
    running_average = averager.send(value)
    print(running_average)

输出:

复制代码
10.0
10.5
11.0
11.5
12.0
12.5

4.总结

In summary, yield is an expression too and we can send value to a generator when it is in suspend state. The first suspend state is achieved by priming the generator.

相关推荐
@小匠15 小时前
Spring Boot Nacos绑定 Map 时中文 key 导致启动失败:一次从复现到源码的排查实录
java·开发语言·前端
Knight_AL15 小时前
Lombok @Builder 踩坑:build() 前后对象类型不一样
android·java·开发语言
金銀銅鐵16 小时前
[Python] 借助 Turtle 逐字展示《醉翁亭记》
python
神明不懂浪漫16 小时前
【第五章】队列
开发语言·数据结构·经验分享·笔记·算法
吃好睡好便好16 小时前
MATLAB仿真框图3
开发语言·matlab·仿真·simulink
-银雾鸢尾-16 小时前
C#中的反射关键类-Type
开发语言·c#
大黄说说16 小时前
Java 与 Kotlin 混合开发避坑指南:老项目平滑迁移 Kotlin 实操手册
java·开发语言·kotlin
breeze jiang16 小时前
JavaScript 单例模式:用静态属性保证 Popup 只创建一次
开发语言·javascript·单例模式
用户70887690393817 小时前
给传统 SaaS 增加 AI 能力:3个真实落地场景
python
卷无止境17 小时前
FastAPI中间件全解析:请求处理链条上的隐形关卡
后端·python·fastapi