很古老的用法了,现在大多用的aiohttp库实现,这篇记录仅仅用做个人的协程底层实现的学习。

争取用看得懂的字来描述问题。

1.什么是yield

如果还没有怎么用过的话,直接把yield看做成一种特殊的return(PS:本质 generator(生成器))

return是返回一个值然后就终断函数了,而yield返回的是一个生成器(PS:不知道的直接看作特殊列表,看下面的代码案例)

# -*- coding: utf-8 -*-
# @Time : 2022/11/10 16:17
# @Author : 红后
# @Email : not_enabled@163.com
# @blog : https://www.cnblogs.com/Red-Sun
# @File : 实例1.py
# @Software: PyCharm def main():
'''
遍历0到4,这五个数,并分别打印
'''
for num in range(5):
yield num if __name__ == '__main__':
for num in main():
print(num)
print('-'*50)
for num in [0, 1, 2, 3, 4]:
print(num)



将它看作列表用for循环遍历,就能取出其中的值。

2.yield于列表的区别

它与原来列表的区别就在于,自带的列表是固定的,而把yield看作列表的话是动态的。

具体案例描述请看代码及备注(PS:个人自己描述的,有不对的地方望各位指点)

# -*- coding: utf-8 -*-
# @Time : 2022/11/14 13:24
# @Author : 红后
# @Email : not_enabled@163.com
# @blog : https://www.cnblogs.com/Red-Sun
# @File : 实例2.py
# @Software: PyCharm def main():
'''
将yield看作一个动态列表,从yield左往右为传出数据,从又往左为传入数据。
PS:有yield存在的那一行,需要从左往右传出数据跑一遍,数据出去以后又要从又往左带接收的数据跑一遍,一共一行跑两边(仅作者个人记忆方法)
'''
num1 = yield
num2 = yield
print(num1, num2)
yield num1 + num2
if __name__ == '__main__':
a = main()
# 第一个next对应第一个yield的右边为空即None,所以动态列表中加入一个参数为None,返回值为列表的-1位是None
print(next(a)) # [None]
# 第二个通过send方法传入一个数1,即在上一次停止的地方从右往左传入参数,所以给num1赋值为1.然后继续找下一个yield,其右边的值依旧为None,加入动态列表,此时返回值-1位依旧是None
print(a.send(1)) # [None, None]
# 第三通过send方法传入一个数2,即在上一次停止的地方从右往左传入参数,所以给num2赋值为2.然后继续找下一个yield,其右边的值为num1 + num2,此时num1为1,num2为2,计算得返回值-1位为3
print(a.send(2)) # [None, None, num1 + num2]

3.yield from 实现协程

yield from 后面需要加可迭代对象

当它后面加上生成器(上述所说的yield这种)便可以实现生成的嵌套

  1. 老板(主程序):调用委派生成器
  2. 包工头(委派生成器):包含yield from表达式的生成器
  3. 打工仔(子生成器):生成器函数

其中委派生成器的作用:在主程序与子生成器之间建立一个双向通道。

所谓双向通道是指,主程序可以将参数通过send传递给子生成器,子生成器的yield的值也可以直接返回给主函数。(PS:委派生成器只有创建通道的作用,没有拦截数据这种功能)

也许有人会想直接用主程序调用子生成器不就行了,而对这的解释是,使用yield from作为中间过渡是为了让它帮我们进行异常处理(PS:类似写程序为了正常运行加上try一个道理)

# -*- coding: utf-8 -*-
# @Time : 2022/11/10 15:13
# @Author : 红后
# @Email : not_enabled@163.com
# @blog : https://www.cnblogs.com/Red-Sun
# @File : coroutines.py
# @Software: PyCharm import requests def coroutines_spider():
'''
子生成器(PS: 打工仔,真正干活的)
'''
response = None # 首次激活返回None,后期网页响应覆盖
while True:
url = yield response
response = requests.get(url) def appoint():
'''
委派生成器,委托子生成器完成具体任务 (PS: 类似包工头负责劳务派遣)
'''
while True:
yield from coroutines_spider() # 建立子生成器和主函数的双通道 def main(url_list: list):
'''
主函数(PS: 相当于老板,张贴招人启示)
'''
ul = appoint() # 创建委派生成器
next(ul) # 激活它
for url in url_list:
response = ul.send(url) # 将url作为参数传递进入子生成器中,返回子生成器yield出来的response
print(response.url, response.status_code) # 打印出response中的链接和状态码 if __name__ == '__main__':
url_list = ['https://www.baidu.com/', 'https://www.4399.com/', 'https://cn.bing.com/', ]
main(url_list=url_list)

最新文章

  1. [原创]Centos7 内部常用软件升级计划
  2. jQuery贪吃蛇--jQuery学习
  3. Scalaz(12)- Monad:再述述flatMap,顺便了解MonadPlus
  4. BZOJ3240 [Noi2013]矩阵游戏
  5. Javascript--练习(包括主界面图片轮播效果)
  6. hdu Collect More Jewels
  7. mysql联合索引详解
  8. 2013-07-24 IT 要闻速记快想
  9. FileObverse文件观察者的Debug报告
  10. PostgreSQL 8.4.1
  11. Linux下载jdk ,Linux如何下载jdk
  12. CSS3的box-sizing属性
  13. 转:Jmeter常见问题 (转载) http://www.51testing.com/?uid-128005-action-viewspace-itemid-84094
  14. UVa 908 - Re-connecting Computer Sites
  15. 【个人笔记】《知了堂》MySQL三种关系:一对一,一对多,多对多。
  16. 前端系列之CSS基础知识概述
  17. 《设计模式之禅》--MVC框架
  18. 西湖论剑2019-msc之奇怪的TTL
  19. buaacoding_2018算法期末上机G题.地铁建设题解
  20. IntelliJ IDEA 使用教程

热门文章

  1. 第七十七篇:ref引用(在vue中引用组件实例)
  2. 第五十篇: webpack中的loader(一) --css-loader
  3. multiprocessing 让子进程忽略信号,手动关闭子进程
  4. 关于KingbaseES临时文件过大问题
  5. ELK套件部署
  6. [AI]-模型测试和评价指标
  7. Python数据科学手册-Pandas数据处理之简介
  8. crictl 命令 - Kubernetes 管理命令详解
  9. ProxySQL(8):SQL语句的重写规则
  10. 编码中的Adapter,不仅是一种设计模式,更是一种架构理念与解决方案