生成器


一、yield运行方式

我们定义一个如下的生成器:

  1. def put_on(name):
  2. print("Hi {}, 货物来了,准备搬到仓库!".format(name))
  3. while True:
  4. goods = yield
  5. print("货物[%s]已经被%s搬进仓库了。"%(goods,name))
  6.  
  7. p = put_on("bigberg")
  8.  
  9. #输出
  10. G:\python\install\python.exe G:/python/untitled/study4/test/double.py
  11.  
  12. Process finished with exit code 0

  当我们把一个函数通过yield转换成生成器,直接运行函数是不会出现结果返回的。因为此时函数已经是个生成器了,我们要通过next()来取得值,并且在遇到yield时再次跳出函数。

  1. print(type(p))
  2.  
  3. #输出
  4. <class 'generator'>

  我们添加next()方法:

  1. def put_on(name):
  2. print("Hi {}, 货物来了,准备搬到仓库!".format(name))
  3. while True:
  4. goods = yield #遇到yield中断
  5. print("货物[%s]已经被%s搬进仓库了。"%(goods,name)) #中断后运行部分
  6.  
  7. p = put_on("bigberg")
  8. p.__next__()
  9.  
  10. #输出
  11. Hi bigberg, 货物来了,准备搬到仓库!

  此时函数中断在 goods = yield 的地方,当我们再次调用next()函数时,函数只会运行中断以后的内容,即上例中的yield下面部分。

  我们再添加一个next():

  1. def put_on(name):
  2. print("Hi {}, 货物来了,准备搬到仓库!".format(name))
  3. while True:
  4. goods = yield
  5. print("货物[%s]已经被%s搬进仓库了。"%(goods,name))
  6.  
  7. p = put_on("bigberg")
  8. p.__next__()
  9. p.__next__()
  10.  
  11. #输出
  12. Hi bigberg, 货物来了,准备搬到仓库!
  13. 货物[None]已经被bigberg搬进仓库了。

  我们可以第二次next()运行的是yield下面的部分内容,但是并没有给goods传值,所以货物是 None。

小结:

  • 通过yield将函数转换为生成器,需要使用next()方法才能运行
  • yield只是保留函数的中断状态,再次调用next()会执行yield后面的部分
  • yield如果没有返回值,会返回一个None空值

二、send()传值

  1. def put_on(name):
  2. print("Hi {}, 货物来了,准备搬到仓库!".format(name))
  3. while True:
  4. goods = yield
  5. print("货物[%s]已经被%s搬进仓库了。"%(goods,name))
  6.  
  7. p = put_on("bigberg")
  8. p.__next__()
  9. p.send("瓜子")
  10.  
  11. #输出
  12. Hi bigberg, 货物来了,准备搬到仓库!
  13. 货物[瓜子]已经被bigberg搬进仓库了。

小结:

  • __next__()只是调用这个yield,也可以说成是唤醒yield,但是不不会给yield传值。
  • send()方法调用yield是,能给yield传值
  • 使用send()函数之前必须使用__next__(),因为先要中断,当第二次调用时,才可传值。
  1. def put_on(name):
  2. print("Hi {}, 货物来了,准备搬到仓库!".format(name))
  3. while True:
  4. goods = yield
  5. print("货物[%s]已经被%s搬进仓库了。"%(goods,name))
  6.  
  7. p = put_on("bigberg")
  8. p.__next__()
  9. p.send("瓜子")
  10. p.send("花生")
  11. p.send("饼干")
  12. p.send("牛奶")
  13.  
  14. #多次调用send()
  15. Hi bigberg, 货物来了,准备搬到仓库!
  16. 货物[瓜子]已经被bigberg搬进仓库了。
  17. 货物[花生]已经被bigberg搬进仓库了。
  18. 货物[饼干]已经被bigberg搬进仓库了。
  19. 货物[牛奶]已经被bigberg搬进仓库了。

 

三、单线程实现并行效果(协程)

  1. import time
  2.  
  3. def put_on(name):
  4. print("Hi {}, 货物来了,准备搬到仓库!".format(name))
  5. while True:
  6. goods = yield
  7. print("货物[%s]已经被%s搬进仓库了。"%(goods,name))
  8.  
  9. def transfer(name):
  10. p = put_on('A')
  11. p2 = put_on('B')
  12. p.__next__()
  13. p2.__next__()
  14. print("%s将货物送来了!"%name)
  15. for i in range(5):
  16. time.sleep(1)
  17. print("%s递过来两件货物"%name)
  18. p.send("瓜子")
  19. p2.send("花生")
  20.  
  21. transfer("bigberg")
  22.  
  23. #输出
  24. Hi A, 货物来了,准备搬到仓库!
  25. Hi B, 货物来了,准备搬到仓库!
  26. bigberg将货物送来了!
  27. bigberg递过来两件货物
  28. 货物[瓜子]已经被A搬进仓库了。
  29. 货物[花生]已经被B搬进仓库了。
  30. bigberg递过来两件货物
  31. 货物[瓜子]已经被A搬进仓库了。
  32. 货物[花生]已经被B搬进仓库了。
  33. bigberg递过来两件货物
  34. 货物[瓜子]已经被A搬进仓库了。
  35. 货物[花生]已经被B搬进仓库了。
  36. bigberg递过来两件货物
  37. 货物[瓜子]已经被A搬进仓库了。
  38. 货物[花生]已经被B搬进仓库了。
  39. bigberg递过来两件货物
  40. 货物[瓜子]已经被A搬进仓库了。
  41. 货物[花生]已经被B搬进仓库了。

  

python--生成器协程运算的更多相关文章

  1. python生成器 协程

    生成器 参考文章:  协程   gevent 生成器进阶 看个例子: def gg(): n='' i=0 while True: n=yield i #通过send传入到n if not n: pa ...

  2. python中和生成器协程相关的yield from之最详最强解释,一看就懂(四)

    如果认真读过上文的朋友,应该已经明白了yield from实现的底层generator到caller的上传数据通道是什么了.本文重点讲yield from所实现的caller到coroutine的向下 ...

  3. python中和生成器协程相关yield from之最详最强解释,一看就懂(二)

    一. 从列表中yield  语法形式:yield from <可迭代的对象实例> python中的列表是可迭代的, 如果想构造一个生成器逐一产生list中元素,按之前的yield语法,是在 ...

  4. python中和生成器协程相关的yield之最详最强解释,一看就懂(一)

    yield是python中一个非常重要的关键词,所有迭代器都是yield实现的,学习python,如果不把这个yield的意思和用法彻底搞清楚,学习python的生成器,协程和异步io的时候,就会彻底 ...

  5. python gevent 协程

    简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...

  6. 关于Python的协程问题总结

    协程其实就是可以由程序自主控制的线程 在python里主要由yield 和yield from 控制,可以通过生成者消费者例子来理解协程 利用yield from 向生成器(协程)传送数据# 传统的生 ...

  7. {python之协程}一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二

    python之协程 阅读目录 一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二 一 引子 本 ...

  8. 【Python】协程

    协程,又称微线程,纤程.英文名Coroutine. 协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用. 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在 ...

  9. 深入理解Python中协程的应用机制: 使用纯Python来实现一个操作系统吧!!

    本文参考:http://www.dabeaz.com/coroutines/   作者:David Beazley 缘起: 本人最近在学习python的协程.偶然发现了David Beazley的co ...

  10. Python之协程(coroutine)

    Python之协程(coroutine) 标签(空格分隔): Python进阶 coroutine和generator的区别 generator是数据的产生者.即它pull data 通过 itera ...

随机推荐

  1. UI优秀框架(库)

    1.vux 官网:https://doc.vux.li/zh-CN/ Github:https://github.com/airyland/vux 13818  Stars  3064 Forks   ...

  2. High School: Become Human(数学思维)

    Year 2118. Androids are in mass production for decades now, and they do all the work for humans. But ...

  3. Beta发布——美工+文案

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2408项目地址:https://coding.net/u/wuyy694/ ...

  4. c# 导入第三方插件(例如pdf控件),莫名有时候成功有时候出错

    问题情境: 正如标题所述: 解决办法: 怀疑是adobe acrobat 9 pro安装文件出错:重新安装,成功. 在这过程中,尝试过福听阅读器,adobe reader等,均正常. 注:1.第三方的 ...

  5. UVALive - 6887 Book Club 有向环的路径覆盖

    题目链接: http://acm.hust.edu.cn/vjudge/problem/129727 D - Book Club Time Limit: 5000MS 题意 给你一个无自环的有向图,问 ...

  6. springMVC 流程

    springMVC流程控制 SpringMVC流程 web.xml 中配置 org.springframework.web.servlet.DispatcherServlet 这一步其实和spring ...

  7. 6/2 sprint2 看板和燃尽图的更新

  8. 学生导师互选系统(php代码规范)

    学生导师互选系统(php代码规范) php编码规范 组名:一不小心就火了 负责项目:学生导师互选系统(安卓端) 编写目的 为了更好的提高团队的的合作效率,保证开发的有效性和合理性,并可最大程度的提高程 ...

  9. week1词频统计

    使用java完成对txt格式的英文短片进行字符提取及统计. package nenu.softWareProject; import java.io.*;import java.util.*; pub ...

  10. ZOJ 2060 A-Fibonacci Again

    https://vjudge.net/contest/67836#problem/A There are another kind of Fibonacci numbers: F(0) = 7, F( ...