本节内容

1、概述

2、生成器执行原理

3、send()和__next__()方法的区别

4、yield实现并行效果

一、概述

  之前只是介绍生成器,那有些同学就说了,这个生成器除了能节省资源,提高工作效率,但是我们再哪些场景下可以用呢?在哪些地方可以体现出它的价值呢?下面我们来逐一解答这些疑问。

二、生成器执行原理

1、执行原理

1
2
3
4
5
6
7
8
9
10
11
12
13
def consumer(name):
    print("%s 准备吃包子啦!"%name)
 
    while True:
        baozi = yield
 
        print("包子[%s]来了,被[%s]吃了"%(baozi,name))
 
= consumer("zhangqigao")
c.__next__()
 
#输出
zhangqigao 准备吃包子啦!

如果我再加一个__next__()方法会有什么效果?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def consumer(name):
    print("%s 准备吃包子啦!"%name)
 
    while True:
        baozi = yield
 
        print("包子[%s]来了,被[%s]吃了"%(baozi,name))
 
= consumer("zhangqigao")
c.__next__()
c.__next__()
 
#输出
zhangqigao 准备吃包子啦!
包子[None]来了,被[zhangqigao]吃了

很明显,第一种情况没有执行"print("包子[%s]来了,被[%s]吃了"%(baozi,name))",这段代码,接下来我们就来调试一下。

2、调试

第一步:生成一个生成器

第二步:执行第一个__next__()方法进入函数,执行到yield时中断,把返回值返回给baozi这个变量:

第三步:开始执行下面的程序,也就执行到了第二个__next__()方法,直接跳转到yield这边,继续上一次的中断往下执行,这样就执行了yield下面的程序,当再次执行到yield关键字时,则继续中断,并且把返回值赋给baozi关键字,如果下面没有其他程序,则程序结束。

小结:

  1. 用yield做生成器,你想把什么返回到外面,你就把yield关键字放在那里。
  2. yield其实是保留了函数的中断状态,返回当前的值。
  3. 如果yield没有返回值,就返回一个空值None

三、send()和__next__()方法的区别

1、send()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def consumer(name):
    print("%s 准备吃包子啦!"%name)
 
    while True:
        baozi = yield
 
        print("包子[%s]来了,被[%s]吃了"%(baozi,name))
 
= consumer("zhangqigao")
c.__next__()  #不使用__next__()方法会报错
b1 = "肉松馅"
c.send(b1)   #调用yield,同时给yield传一个值
b2 = "韭菜馅"
c.send(b2)
 
#输出
zhangqigao 准备吃包子啦!
包子[肉松馅]来了,被[zhangqigao]吃了
包子[韭菜馅]来了,被[zhangqigao]吃了

从上面可以看出send()和__next__()方法的区别:

  1. __next__()只是调用这个yield,也可以说成是唤醒yield,但是不不会给yield传值。
  2. send()调用这个yield或者说唤醒yield同时,也活给yield传一个值。
  3. 使用send()函数之前必须使用__next__(),因为先要中断,当第二次调用时,才可传值。

为什么给消费者传值时,必须先执行__next__()方法?

因为如果不执行一个__next__()方法,只是把函数变成一个生成器,你只有__next__()一下,才能走到第一个yield,然后就返回了,调用下一个send()传值时,才会发包子。

四、yield实现并行效果

yield还有一个更强大的功能,就是:单线程实现并发效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import time
 
def consumer(name):
    print("%s 准备吃包子啦!"%name)
 
    while True:
        baozi = yield
 
        print("包子[%s]来了,被[%s]吃了"%(baozi,name))
 
 
def producer(name):
    = consumer("A")
    c2 = consumer("B")
    c.__next__()
    c2.__next__()
    print("老子准备吃包子啦!")
    for in range(10):
        time.sleep(1)
        print("做了一个包子,分两半")
        c.send(i)
        c2.send(i)
 
producer("zhangqigao")

这个是生产者消费者模式,这个也就是后面协程的效果,这个我们后续再讲,先了解一下,生成器可以实现并发效果,极大的提高程序的运行效率。

函数和常用模块【day05】:生成器并行计算(五)的更多相关文章

  1. 函数和常用模块【day05】:生成器(四)

    本节内容 1.概述 2.列表生成式 3.生成器 4.函数实现生成器 5.生成器表达式 一.概述 我们在使用一组数据时,通常情况下会定义一个列表,然后循环里面的元素,但是你想过没有,如果你只需要使用列表 ...

  2. 函数和常用模块【day05】:迭代器(六)

    本节内容 1.简书 2.可迭代对象 3.迭代器 4.rang方法 5.总结 一.简述 我们经常使用for循环去遍历一些序列数据,但是我们有的时间发现for循环的效率很低,而且很占用了大量的硬件资源,但 ...

  3. 函数和常用模块【day06】:shelve模块(五)

    本节内容 1.简述 2.shelve概念 3.shelve模块使用 4.总结 一.简述 之前我们说不管是json也好,还是pickle也好,在python3中只能dump一次和load一次,不能dum ...

  4. 函数和常用模块【day05】:文件目录开发规范(七)

    本节内容 1.背景 2.设计目录结构的好处 3.关于readme的内容 4.关于requirements.txt和setup.py 5.关于配置文件的使用方法 一.背景 "设计项目目录结构& ...

  5. 函数和常用模块【day05】:不同目录间进行模块调用(八)

    本节内容 1.背景 2.函数功能解释 3.绝对路径和相对路径 4.不同目录间进行模块调用 一.背景 之前写了软件开发目录规范这篇博客,相信很多人都已经知道,我们在写程序时需要遵循一定的规范,不然,就算 ...

  6. 函数和常用模块【day05】:装饰器高潮(三)

    本节内容 1.概述 2.装饰器定义 3.装饰器定义 4.带参数的生成器 一.概述 我们之前介绍了大幅片的内容,感觉跟装饰器半毛钱关系都没有,其实不然,我们分别详细阐述了高阶函数和内置函数,下面我们就来 ...

  7. 函数和常用模块【day05】:装饰器前奏(一)

    本节内容 定义 原则 实现装饰器的储备知识 函数及变量 高阶函数 一.定义 1.装饰器:本质是函数. 2.功能:用来装饰其他函数,顾名思义就是,为其他的函数添加附件功能的. 二.原则 不能修改被装饰函 ...

  8. 函数和常用模块【day05】:装饰器前戏(二)

    本节内容 嵌套函数 局部作用域和全局作用域的访问顺序 一.嵌套函数 1.定义 在一个函数的函数体内,用def 去声明一个函数,而不是去调用其他函数,称为嵌套函数. 1 2 3 4 5 6 7 8 9 ...

  9. 函数和常用模块【day04】:递归(五)

    本节内容 作用域.局部和全局变量 递归 函数式编程 高阶函数和eval()函数 一.概述 在函数内部,可以调用其他函数.但是一个函数在内部调用自身,这个函数被称为递归函数. 二.简单介绍 那递归具体是 ...

随机推荐

  1. 移动端页面滑动时候警告:Unable to preventDefault inside passive event listener due to target being treated as passive.

    移动端项目中,在滚动的时候,会报出以下提示: [Intervention] Unable to preventDefault inside passive event listener due to ...

  2. 微信小程序之路由

    1. 路由方式 路由方式 触发时机 路由前页面 路由后页面 初始化 小程序打开的第一个页面 onLoad, onShow 打开新页面 调用 API wx.navigateTo 或使用组件 onHide ...

  3. SSISDB5:使用TSQL脚本执行Package

    SSISDB 系列随笔汇总: SSISDB1:使用SSISDB管理Package SSISDB2:SSIS工程的操作实例 SSISDB3:Package的执行实例 SSISDB4:当前正在运行的Pac ...

  4. Flask学习-前言

    前言 使用Flask断断续续加起来快一年了,但是一直没有从源码层去了解其实现原理.加上自己python基础不扎实,所以准备从看一个开源项目开始,希望能够从中窥得武功精髓,让自己水平更上一层楼. Fla ...

  5. stl源码剖析 详细学习笔记 空间配置器

    //---------------------------15/04/05---------------------------- /* 空间配置器概述: 1:new操作包含两个阶段操作 1>调 ...

  6. 关于GitHub上传没有记录(小绿块不显示的问题)

    最近开始使用上github来上传保存自己在学习中所写过的代码,打算将自己每天的成果能有个保存,然后就利用上GitHub这么一个利器. 听说GitHub的那个绿块是用来记录每天的上传记录的,结果我将代码 ...

  7. WebStorm安装

    用到的链接: WebStorm官网:https://www.jetbrains.com/webstorm 破解补丁与注册码网址:http://idea.lanyus.com/ 有条件的朋友请购买正版. ...

  8. 0.1 Maven相关知识(项目开发基础)

    一.Maven 1.1Maven是什么 Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件. Maven这个单词来自于意第绪语(犹太语),意为知识的 ...

  9. Call actvity after viewpager is finished

    private OnPageChangeListener mListener = new OnPageChangeListener() { @Override public void onPageSe ...

  10. 11.19daily_scrum

    本阶段的工作内容为测试并且撰写笔记本APP应用的测试报告,目的在于总结测试阶段的测试以及分析测试结果,描述系统是否符合需求,测试软件功能的完善性.除了音频界面还未完成,其他部分均已开始实现测试功能,具 ...