python yield和send

包含yield表达式的函数是特殊的函数,叫做生成器函数(generator function),被调用时将返回一个迭代器(iterator),调用时可以使用next或send(msg)。它的用法与return相似,区别在于它会记住上次迭代的状态,继续执行。 
send(msg)与next()的区别在于send可以传递参数给yield表达式,这时传递的参数会作为yield表达式的值,而yield的参数是返回给调用者的值。初始调用时必须先next()或send(None),否则会报错。 

举个例子: 
1.png  
首先生成一个迭代器f,f.next()会使生成器函数执行到yield,生成一个值然后挂起。 
2.png  
然后f.next()或f.send(msg)会在生成器函数内部返回值,执行到下一个yield,生成值后挂起 
3.png  
然后f.next()或f.send(msg)会在生成器函数内部返回值,意图执行到下一个yield,但是后面没有yield了,所以抛出异常。 

使用yield可以有效简化代码,并减少空间浪费。 
举个简单例子:列表中的每个元素+1 
传统写法: 
Python代码
  1. def addlist(alist):   
  2.     r = []   
  3.     for i in alist:   
  4.         r.append(i+1)   
  5.     return r  
复制代码
yield写法: 
Python代码
  1. def addlist(alist):     
  2.     for i in alist:     
  3.         yield i + 1   
复制代码
当然对于这种简单的问题: 

Python代码
  1. [i+1 for i in alist]  
复制代码
### 使用 `send()` 方法与 `yield` 协同工作的机制 在 Python 中,`send()` 方法允许向生成器函数传递数据并恢复其执行状态。当调用带有参数的 `send()` 时,该参数会成为上一次 `yield` 表达式的返回值。 #### 发送数据到生成器 考虑如下定义的任务调度示例: ```python def task(name): print(f"任务 {name} 开始") while True: received = yield # 此处暂停等待接收外部输入的数据 print(f"任务 {name} 接收到: {received}") ``` 在此代码片段中,每当遇到 `yield` 关键字时,生成器就会挂起自身的执行直到接收到新的消息为止。此时可以利用 `send()` 函数来继续流程并向内部传入新值[^3]。 为了启动上述创建好的协程对象,在首次激活之前需先调用一次不带参数的 `.next()` 或者等价形式 `.__next__()` 来预热它;之后就可以通过多次调用 `send()` 将不同信息注入给定的任务实例里了。 下面展示了一个完整的例子说明怎样在一个简单的事件驱动环境中运用这些特性来进行多任务处理: ```python def scheduler(): # 创建两个不同的子任务作为独立的协程实体 task1 = task("A") task2 = task("B") # 预激化各个协程准备就绪 next(task1) next(task2) try: # 循环模拟交替运行多个任务的过程 for i in range(4): if i % 2 == 0: task1.send(f"奇数轮次{i}: 数据X") # 向task1发送特定字符串 else: task2.send(f"偶数轮次{i}: 数据Y") # 同样地更新另一个任务的状态 except StopIteration as e: pass scheduler() ``` 此脚本展示了如何借助于 `send()` `yield` 实现基本的任务切换逻辑,并且能够灵活控制各部分之间的交互行为。值得注意的是,一旦某个协程完成了它的生命周期,则应当妥善捕获可能抛出的异常情况以确保整个系统的稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值