send()方法

文档定义

generator.send(value)

Resumes the execution and “sends” a value into the generator function. The value argument becomes the result of the current yield expression. The send() method returns the next value yielded by the generator, or raises StopIteration if the generator exits without yielding another value. When send() is called to start the generator, it must be called with None as the argument, because there is no yield expression that could receive the value.

  • 这里要注意send方法和next方法的区别,在于send方法会首先把上一次挂起的yield语句的返回值通过参数设定,从而实现和生成器方法的交互.
  • send(None)next()方法完全等价.

代码示例

  1. def gen(): 


  2. x = yield 1 


  3. print('gen---{0}'.format(x)) 


  4. y = yield 2 


  5. print('gen---{0}'.format(y)) 


  6. z = yield 3 


  7. print('gen---{0}'.format(z)) 



  8. g = gen() 



  9. result0 = g.send(None) 


  10. print('main---{0}'.format(result0)) 


  11. result1 = g.send(111) 


  12. print('main---{0}'.format(result1)) 


  13. result2 = g.send(222) 


  14. print('main---{0}'.format(result2)) 


  15. result3 = g.send(333) 


  16. print('main---{0}'.format(result3)) 



把上面那一段读懂之后 这个结果就好理解了.


pic-1582723999405.png
  • 首先result0 = g.send(None)执行,激活生成器到yeild 1. 生成器返回1 输出main---1
  • 第二步到result1 = g.send(111) 从上次挂起的地方向生成器传递111的值,也就是x=111 接着往下执行输出gen---111
  • 往下执行到yeild 2,返回2 然后打印main---2,同理下一步到result2 = g.send(222)
  • y得到值222,输出gen---222
  • 然后继续执行到yeild 3,返回3,输出main---3
  • 再下一步send(333)的时候,从上次终端的位置z=yield 3获取输入值,z被赋值为333,打印gen---333
  • 往下没有yield了,抛出StopIteration的异常.

刚开始没搞明白是因为没有搞明白这个send进去的值在那里接收. 这里注意的是send进去的值在上一次yeild挂起的位置接收.

throw()方法

文档定义

generator.throw(type[, value[, traceback]])

Raises an exception of type type at the point where the generator was paused, and returns the next value yielded by the generator function. If the generator exits without yielding another value, a StopIteration exception is raised. If the generator function does not catch the passed-in exception, or raises a different exception, then that exception propagates to the caller.

注意!!! 在上次yeild挂起的地方传入exception!!!

代码示例1-异常在生成器中被捕获

  1. def gen(): 


  2. n=0 


  3. while True: 


  4. try: 


  5. yield n 


  6. n +=1 


  7. except OverflowError: 


  8. print("got it!") 



  9. g = gen() 



  10. result1 = next(g) 


  11. print(result1) 



  12. result2 = g.throw(OverflowError) 


  13. print(result2) 



  14. result3 = next(g) 


  15. print(result3) 




pic-1582723999406.png

结果比较简单,我们来看一下:

  • result1 = next(g) 没毛病 n=0进去的,然和yield出来的也是0
  • result2=g.throw(OverflowError) 在上次挂起的地方,传入这个异常. 然后异常被捕获,n还是0 因为下面的n+=n跟本没执行.
  • 下面就没啥好解释的了

代码示例2-异常在生成器中没有被捕获

  1. import sys 


  2. def gen(): 


  3. n = 0 


  4. while True: 


  5. yield n 


  6. n+=1 



  7. g = gen() 



  8. result1 = next(g) 


  9. print(result1) 



  10. try: 


  11. result2 = g.throw(NameError) 


  12. except NameError: 


  13. print('Main function catch the exception') 


  14. print(sys.exc_info()) 



  15. try: 


  16. print(result2) 


  17. except NameError: 


  18. print('cathe NameError') 


  19. print(sys.exc_info()) 



  20. print(next(g)) 



看着例子

  • throw的异常在生成器内部没有捕获的话,会直接传递到调用生成器的函数中去.
  • 这里result2因为赋值还没有发生就抛出了异常,所以result2是不存在的.
  • 在异常抛出后,生成器终止,不能再继续调用.

pic-1582723999406.png

代码示例3

  1. def gen(): 


  2. try: 


  3. # 注意是在当前暂停的 yield 处抛出异常 


  4. # 所以要在这里捕获 


  5. yield 1 


  6. except Exception as e: 


  7. print('在生成器内部捕获了异常') 


  8. print(e.args) 


  9. print('处理完毕,假装什么也没发生') 



  10. # yield 2 



  11. g = gen() 



  12. print(next(g)) 



  13. result = g.throw(TypeError,'类型错误~~') 



  14. print(result) 



  • print(next(g)) 这里没问题,正常返回1
  • 下一步result = g.throw(TypeError,'类型错误~~')把异常整进去之后,记得!是从上一次yeild挂起的地方!!! 直接被生成器中的except捕获了.
  • 之后因为下面没有yeild的值了,所以会报一个StopIteration的异常回来.

pic-1582723999406.png

close()方法

文档定义

generator.close()

Raises a GeneratorExit at the point where the generator function was paused. If the generator function then exits gracefully, is already closed, or raises GeneratorExit (by not catching the exception), close returns to its caller. If the generator yields a value, a RuntimeError is raised. If the generator raises any other exception, it is propagated to the caller. close() does nothing if the generator has already exited due to an exception or normal exit.

文档解读:

  • 在生成器暂停的地方会返回GeneratorExit

代码示例1-不在生成器内捕获GeneratorExit异常

  1. def gen(): 


  2. print("1 will be yielded") 


  3. yield 1 


  4. print('2 will be yielded') 


  5. yield 2 



  6. g = gen() 



  7. print(next(g)) 


  8. g.close() 


  9. print(next(g)) 




pic-1582723999406.png
  • close方法正常返回,且生成器内的GeneratorExit不传递给调用方
  • close之后生成器注销,所以在此next的时候会报StopIteration异常

代码示例2

  1. def gen(): 


  2. print("1 will be yielded") 


  3. try: 


  4. yield 1 


  5. except GeneratorExit: 


  6. print('get generator exit exception') 


  7. print("generator finished") 



  8. g = gen() 



  9. print(next(g)) 


  10. g.close() 



生成器退出的时候抛出StopIteration异常,但是这个异常不会传递给调用方.

代码示例3--GeneratorExit之后还有yield语句

  1. def gen(): 


  2. try: 


  3. yield 1 


  4. except GeneratorExit: 


  5. print('捕获到 GeneratorExit') 


  6. print('尝试在 GeneratorExit 产生后 yield 一个值') 


  7. yield 2 



  8. print('生成器结束') 



  9. g = gen() 


  10. next(g) 


  11. g.close() 




pic-1582723999407.png
  • 在GeneratorExit抛出之后还有yield语句的话 有可能会产生RuntimeError.
  • 所以不要在except和finally中写yield,因为不知道啥时候就会出问题.
  • 另外,在生成器被垃圾回收的时候,也会自动调用close方法

最后,对于一个已经关闭的生成器对象,close方法不会有任何的作用. 不执行任何操作.

换句话说,只有激活的生成器才会触发GeneratorExit异常.

终于特么写完了...累死我了...

本文参考了 CSDN(团子大元帅)的文章

Python 生成器与它的 send,throw,close 方法

python随用随学20200221-生成器中的send(),throw()和close()方法的更多相关文章

  1. python特性(八):生成器对象的send方法

    生成器对象是一个迭代器.但是它比迭代器对象多了一些方法,它们包括send方法,throw方法和close方法.这些方法,主要是用于外部与生成器对象的交互.本文先介绍send方法. send方法有一个参 ...

  2. Python编程系列---获取请求报文行中的URL的几种方法总结

    在浏览器访问web服务器的时候,服务器收到的是一个请求报文,大概GET请求的格式大概如下: 先随便拿到一个请求报文,蓝色即为我们要获取的 GET  /index.html  HTTP/1.1  Hos ...

  3. [Python] 文科生零基础学编程系列二——数据类型、变量、常量的基础概念

    上一篇:[Python] 文科生零基础学编程系列--对象.集合.属性.方法的基本定义 下一篇: (仍先以最简单的Excel的VBA为例,语法与Python不同,但概念和逻辑需要理解透彻) p.p1 { ...

  4. python生成器中yield和send分析

    生成器 在python中生成器是指用代码实现迭代器的的功能本质还是迭代器,只不过是代码实现迭代器功能.在python中生成器是由函数实现的,通常我们在函数中加入yeild就可以实现生成器. 生成器中y ...

  5. python极简教程05:生成器和匿名函数

    测试奇谭,BUG不见. 讲解之前,我先说说我的教程和网上其他教程的区别: 1 我分享的是我在工作中高频使用的场景,是精华内容: 2 我分享的是学习方法,亦或说,是指明你该学哪些.该重点掌握哪些内容: ...

  6. python基础知识7——迭代器,生成器,装饰器

    迭代器 1.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退.另外,迭代器 ...

  7. 【转载】教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神

    原文:教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神 本博文将带领你从入门到精通爬虫框架Scrapy,最终具备爬取任何网页的数据的能力.本文以校花网为例进行爬取,校花网:http:/ ...

  8. Python 迭代器之列表解析与生成器

     [TOC] 1. 列表解析 1.1 列表解析基础 列表解析把任意一个表达式应用到一个迭代对象中的元素 Python内置ord函数会返回一个字符的ASCII整数编码(chr函数是它的逆过程, 它将A ...

  9. Python中的str与unicode处理方法

    Python中的str与unicode处理方法 2015/03/25 · 基础知识 · 3 评论· Python 分享到:42 原文出处: liuaiqi627 的博客    python2.x中处理 ...

随机推荐

  1. 【阿K学Python系列】一Python基础语法(二)

    前言 通过上一章的学习[阿k学Python]一Python入门(一),我们已经初步了解到Python是一种解释型.面向对象.动态数据类型的高级程序设计语言,当然也是一门脚本语言,像前端需要学习的Jav ...

  2. V8垃圾回收?看这篇就够了!

    什么是内存管理 内存管理是控制和协调应用程序访问电脑内存的过程.这个过程是复杂的,对于我们来说,可以说相当于一个黑匣子. 当咱们的应用程序运行在某个操作系统中的时候,它访问电脑内存(RAM)来达成下列 ...

  3. Warshall算法求传递闭包及具体实现

    传递闭包 在数学中,在集合 X 上的二元关系 R 的传递闭包是包含 R 的 X 上的最小的传递关系. 例如,如果 X 是(生或死)人的集合而 R 是关系“为父子”,则 R 的传递闭包是关系“x 是 y ...

  4. 搭建本地测试es集群

    需求 在本地搭建es+kibana+elasticsearch-head 搭建环境 mac本地,使用docker+docker-compose 方式搭建 设置docker 内存8G 搭建es和es+h ...

  5. nmap详解之基础概述

    概述 nmap是一个网络探测和安全扫描程序,系统管理者和个人可以使用这个软件扫描大型的网络,获取那台主机正在运行以及提供什么服务等信息.nmap支持很多扫描技术,例如:UDP.TCP connect( ...

  6. Centos 7 最小化部署zabbix

    前言 文章内容是作者本人编写,之前一直放在word文档中,突然有闲情转移到博客上来了,欢迎后续观看者有问题找我探讨~~~ 废话不多说,先说下原理吧 概述 工作原理 通过c/s模式采集数据,基于b/s模 ...

  7. Shell之哈希表

    前言 linux系统下会有一个hash表,当你刚开机时这个hash表为空,每当你执行过一条命令时,hash表会记录下这条命令的路径,就相当于缓存一样.第一次执行命令shell解释器默认的会从PATH路 ...

  8. springIOC源码接口分析(七):ApplicationEventPublisher

    一 定义方法 此接口主要是封装事件发布功能的接口,定义了两个方法: /** * 通知应用所有已注册且匹配的监听器此ApplicationEvent */ default void publishEve ...

  9. springIOC源码接口分析(一):BeanFactory

    一 应用场景 BeanFactory接口定义了IOC容器的最基本功能,提供了容器应该具有的功能规范,所有的容器都应该实现这个接口 BeanFactory设计了getBean方法用来获取容器中的Bean ...

  10. Windbg实用手册

    Windbg工作中用的不多,所以命令老是记不住,每次使用都要重新查命令,挺烦. 趁这次培训的机会好好测试和总结了一下,下次再用就方便多了. 在这里一起共享一下,如果有错误,请指正. 基本知识和常用命令 ...