yield作用

  简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator。下面以斐波拉契数列来做个说明:

# 普通的函数实现
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
n = n + 1
return 'done'
"""不足:
在 fab 函数中用 print 打印数字会导致该函数可复用性较差
因为其他函数无法获得该函数生成的数列。
""" # 返回一个 List
def fib(max):
n, a, b = 0, 0, 1
L = []
while n < max:
L.append(b)
a, b = b, a + b
n = n + 1
return L
"""不足
该函数在运行中占用的内存会随着参数 max 的增大而增大,如果要控制内存占用,最好不要用 List
来保存中间结果,而是通过iterable对象来迭代。
""" # 使用yield
def fab(max):
n, a, b = 0, 0, 1
while n < max:
yield b
# print b
a, b = b, a + b
n = n + 1
"""
带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,
调用 fab(5) 不会执行fab函数,而是返回一个 iterable对象
"""

下面执行yield版的fab函数:

# 运行
for n in fab(5):
print(n) # 结果
1
1
2
3
5

  在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。

yield send方法

  关于生成器中的send方法,之前没理解,只知道有一个next方法。通过下面代码实例,记录一下自己的理解:

def func1():  # 生成器函数
x = yield 1
print('This is x in func1: ', x)
x = yield x
# print('This is x:', x) f1 = func1()
print('This is next(f1): ', next(f1))
# 当调用next(f1)方法时,python首先会执行func1方法的yield 1语句
# next方法返回值为yield关键字后面表达式的值,即为1
# 此时方法func1中断执行,x的赋值以及之后的语句,不再执行 # 执行send方法或next方法:
print("This is f1.send('e'):", f1.send('e'))
# print("Second next:", next(f1)) # 当调用f1.send('e')方法时,恢复之前yield引起的中断
# 继续执行 x = yield 1,对x赋值
# 此时(yield 1)的返回值是send方法的参数值'e',并将其赋值给x
# 然后继续执行 print('This is x in func1: ', x)
# 执行结果是This is x in func1: e # 当调用next方法—>print("Second next:", next(f1))
# func1会从之前的中断—>yield 1语句,继续运行
# 语句 print('This is x in func1: ', x) 将被执行。
# 但是,此时yield 1的返回值是None,并将其赋值给x
# 因此,执行结果是:This is x in func1: None # 如果调用f1.send('e')方法,则接下来继续执行,会遇到yield x语句
# func1再次被挂起。
# 此时,send方法的返回值为yield关键字后面表达式的值,即是x的值'e'
# 执行结果是:This is f1.send('e'): e
# 如果func1方法内无 yield x 语句,将会报错:StopIteration # 如果此时再次调用send方法
# print("This is f1.send('f'):", f1.send('f')) # 此时表达式(yield x)的返回值定义为send方法参数的值,即为'f'
# 接下来x = yield x 这一赋值语句会将x的值置为'f'
# 继续运行,func1方法执行完毕,抛出StopIteration异常
# f1.send('f')也就没有返回值了。
# 但是,我们可以在func1方法,x = yield x语句后,中加入一条语句
# print('This is last x: ', x),用来测试x的值‘f’

总之,send方法和next方法的区别在于,执行send方法时,会首先把send方法内的参数赋值给上一次挂起的yield语句的返回值。但是需要注意,在一个生成器对象没有执行next方法之前,由于没有yield语句被挂起,所以执行send方法会报错:

TypeError: can't send non-None value to a just-started generator

但是,下面的语句是可行的:

f2 = func1()
print("Send None value: ", f3.send(None))
# 运行结果
# Send None value: 1

当send方法的参数为None时,它与next方法完全等价。但是注意,虽然上面的代码可以接受,但是不规范。所以,在调用send方法之前,还是先调用一次next方法为好。

  以上,就是我通过查找资料,搞清楚yield 中send方法的过程与心得。感谢:https://blog.csdn.net/hedan2013/article/details/56293173  提供的参考。

【Python学习之十】yield之send方法的更多相关文章

  1. Python 学习 第十篇 CMDB用户权限管理

    Python 学习 第十篇 CMDB用户权限管理 2016-10-10 16:29:17 标签: python 版权声明:原创作品,谢绝转载!否则将追究法律责任. 不管是什么系统,用户权限都是至关重要 ...

  2. python学习日记(基础数据类型及其方法01)

    数字 int 主要是用于计算的,常用的方法有一种 #既十进制数值用二进制表示时,最少使用的位数i = 3#3的ASCII为:0000 0011,即两位 s = i.bit_length() print ...

  3. Python学习(十) —— 常用模块

    一.collections模块 在内置数据类型(dict.list.set.tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter.deque.defaultdic ...

  4. Python学习笔记(十二)—Python3中pip包管理工具的安装【转】

    本文转载自:https://blog.csdn.net/sinat_14849739/article/details/79101529 版权声明:本文为博主原创文章,未经博主允许不得转载. https ...

  5. 【Python学习之十】操作数据库

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 python3.6 操作mysql数据库 1.安装pymysql模块p ...

  6. python学习第十四天字典的del(),pop().popitem(),clear()删除方法

    字典的每个键值 key=>value 数据类型,字典的key是唯一的,Value可以一样 names={'玖乐公司网址':‘www.96net.com.cn’,"电池网":' ...

  7. python学习笔记(十 三)、网络编程

    最近心情有点儿浮躁,难以静下心来 Python提供了强大的网络编程支持,很多库实现了常见的网络协议以及基于这些协议的抽象层,让你能够专注于程序的逻辑,而无需关心通过线路来传输比特的问题. 1 几个网络 ...

  8. Python学习二十八周(vue.js)

    一.指令 1.一个例子简单实用vue: 下载vue.js(这里实用1.0.21版本) 编写html代码: <!DOCTYPE html> <html lang="en&qu ...

  9. Python学习日记(十) 生成器和迭代器

    使用dir()我们可以知道这个数据类型的内置函数有什么方法: print(dir(int)) print(dir(bool)) print(dir([])) print(dir({})) print( ...

随机推荐

  1. 读取properties和xml中配置文件的值

    五种方式让你在java中读取properties文件内容不再是难题 在java中读取properties和xml文件中的方法:https://www.cnblogs.com/ConfidentLiu/ ...

  2. vue——运行一个项目

    教程:https://segmentfault.com/a/1190000009871504 启动:cnpm run dev

  3. 使用Telerik StyleMananger 改变Silverlight Button样式

    Telerik 支持更改以下控件样式 System.Windows.Button System.Windows.ScrollViewer System.Windows.CheckBox System. ...

  4. Spring 学习(三)AOP

    (1)AOP概述 - AOP:面向切面编程,扩展功能不修改源代码实现 - AOP采取横向抽取机制,取代了传统的纵向继承体系重复性代码 (2)AOP底层原理 原始方法------->纵向继承体系 ...

  5. 初识quartz 并分析 项目中spring整合quartz的配置【原创+转载】

    初识quartz 并分析 项目中spring整合quartz的配置[原创+转载]2018年01月29日 12:08:07 守望dfdfdf 阅读数:114 标签: quartz 更多个人分类: 工具 ...

  6. 《给业余投资者的10条军规 (雪球「岛」系列) (闲来一坐s话投资》读书笔记

    大多数进入股市的人,往往有着非一般的自信.比如,读了几本大师的书,就感觉自己掌握了什么秘笈,又恰逢账面浮盈,自信心更是前所未有的膨胀. 有人说,投资者不经过一轮牛熊转换是成熟不起来的. 古人早就有言, ...

  7. Life here can be a dream come true!

    Life here can be a dream come true!美梦迟早会成真的!

  8. Eucalyptus4.0 管理页面介绍

    桉树配置好之后,我们可以通过web方式登陆桉树管理页面,实现对实例的启动,新建.删除,以及相关的配置操作.这里我们使用的是内网地址:http://192.168.20.60:8888/, 用户名密码默 ...

  9. Remote System Explorer Operation在eclipse后台一直跑 解决办法

    在用eclipse开发时,经常遇到卡死的情况,其中一种就是右下角出现:“Remote System Explorer Operation”,解决方案如下: 第一步:Eclipse -> Pref ...

  10. centos7.3.1611安装及初始配置

    安装前规划: 主机名称 网络配置 分区配置 分区配置 自定义分区,标准分区 /boot 200M (可选) swap 内存1.5倍到2倍(不大于8G) / 根分区(100G到200G) 其余的备用(数 ...