Python生成器(send,close,throw)方法详解
《Python生成器》一节中,详细介绍了如何创建一个生成器,以及生成器的基础用法。本节将在其基础上,继续讲解和生成器有关的一些方法。
值得一提的是,send() 方法可带一个参数,也可以不带任何参数(用 None 表示)。其中,当使用不带参数的 send() 方法时,它和 next() 函数的功能完全相同。例如:
注意,带参数的 send(value) 无法启动执行生成器函数。也就是说,程序中第一次使用生成器调用 next() 或者 send() 函数时,不能使用带参数的 send() 函数。
举个例子:
1) 首先,构建生成器函数,并利用器创建生成器(对象)f 。
2) 使用生成器 f 调用无参的 send() 函数,其功能和 next() 函数完全相同,因此开始执行生成器函数,即执行到第一个 yield "hello" 语句,该语句会返回 "hello" 字符串,然后程序停止到此处(注意,此时还未执行对 bar_a 的赋值操作)。
3) 下面开始使用生成器 f 调用有参的 send() 函数,首先它会将暂停的程序开启,同时还会将其参数“新宝库”赋值给当前 yield 语句的接收者,也就是 bar_a 变量。程序一直执行完 yield bar_a 再次暂停,因此会输出“新宝库”。
4) 最后依旧是调用有参的 send() 函数,同样它会启动餐厅的程序,同时将参数“https://www.xinbaoku.com”传给 bar_b,然后执行完 yield bar_b 后(输出 https://www.xinbaoku.com),程序执行再次暂停。
因此,该程序的执行结果为:
举个例子:
注意,虽然通过捕获 GeneratorExit 异常,可以继续执行生成器函数中剩余的代码,带这部分代码中不能再包含 yield 语句,否则程序会抛出 RuntimeError 异常。例如:
另外,生成器函数一旦使用 close() 函数停止运行,后续将无法再调用 next() 函数或者 __next__() 方法启动执行,否则会抛出 StopIteration 异常。例如:
举个例子:
Python生成器send()方法
我们知道,通过调用 next() 或者 __next__() 方法,可以实现从外界控制生成器的执行。除此之外,通过 send() 方法,还可以向生成器中传值。值得一提的是,send() 方法可带一个参数,也可以不带任何参数(用 None 表示)。其中,当使用不带参数的 send() 方法时,它和 next() 函数的功能完全相同。例如:
def intNum(): print("开始执行") for i in range(5): yield i print("继续执行") num = intNum() print(num.send(None)) print(num.send(None))程序执行结果为:
开始执行
0
继续执行
1
这里重点讲解一些带参数的 send(value) 的用法,其具备 next() 函数的部分功能,即将暂停在 yield 语句出的程序继续执行,但与此同时,该函数还会将 value 值作为 yield 语句返回值赋值给接收者。注意,虽然 send(None) 的功能是 next() 完全相同,但更推荐使用 next(),不推荐使用 send(None)。
注意,带参数的 send(value) 无法启动执行生成器函数。也就是说,程序中第一次使用生成器调用 next() 或者 send() 函数时,不能使用带参数的 send() 函数。
举个例子:
def foo(): bar_a = yield "hello" bar_b = yield bar_a yield bar_b f = foo() print(f.send(None)) print(f.send("新宝库")) print(f.send("https://www.xinbaoku.com"))分析一下此程序的执行流程:
1) 首先,构建生成器函数,并利用器创建生成器(对象)f 。
2) 使用生成器 f 调用无参的 send() 函数,其功能和 next() 函数完全相同,因此开始执行生成器函数,即执行到第一个 yield "hello" 语句,该语句会返回 "hello" 字符串,然后程序停止到此处(注意,此时还未执行对 bar_a 的赋值操作)。
3) 下面开始使用生成器 f 调用有参的 send() 函数,首先它会将暂停的程序开启,同时还会将其参数“新宝库”赋值给当前 yield 语句的接收者,也就是 bar_a 变量。程序一直执行完 yield bar_a 再次暂停,因此会输出“新宝库”。
4) 最后依旧是调用有参的 send() 函数,同样它会启动餐厅的程序,同时将参数“https://www.xinbaoku.com”传给 bar_b,然后执行完 yield bar_b 后(输出 https://www.xinbaoku.com),程序执行再次暂停。
因此,该程序的执行结果为:
hello
新宝库
https://www.xinbaoku.com
Python生成器close()方法
当程序在生成器函数中遇到 yield 语句暂停运行时,此时如果调用 close() 方法,会阻止生成器函数继续执行,该函数会在程序停止运行的位置抛出 GeneratorExit 异常。举个例子:
def foo(): try: yield 1 except GeneratorExit: print('捕获到 GeneratorExit') f = foo() print(next(f)) f.close()程序执行结果为:
1
捕获到 GeneratorExit
注意,虽然通过捕获 GeneratorExit 异常,可以继续执行生成器函数中剩余的代码,带这部分代码中不能再包含 yield 语句,否则程序会抛出 RuntimeError 异常。例如:
def foo(): try: yield 1 except GeneratorExit: print('捕获到 GeneratorExit') yield 2 #抛出 RuntimeError 异常 f = foo() print(next(f)) f.close()程序执行结果为:
1
捕获到 GeneratorExit Traceback (most recent call last):
File "D:\python3.6\1.py", line 10, in <module>
f.close()
RuntimeError: generator ignored GeneratorExit
另外,生成器函数一旦使用 close() 函数停止运行,后续将无法再调用 next() 函数或者 __next__() 方法启动执行,否则会抛出 StopIteration 异常。例如:
def foo(): yield "www.xinbaoku.com" print("生成器停止执行") f = foo() print(next(f)) #输出 "www.xinbaoku.com" f.close() next(f) #原本应输出"生成器停止执行"程序执行结果为:
www.xinbaoku.com
Traceback (most recent call last):
File "D:\python3.6\1.py", line 8, in <module>
next(f) #原本应输出"生成器停止执行"
StopIteration
Python生成器throw()方法
生成器 throw() 方法的功能是,在生成器函数执行暂停处,抛出一个指定的异常,之后程序会继续执行生成器函数中后续的代码,直到遇到下一个 yield 语句。需要注意的是,如果到剩余代码执行完毕没有遇到下一个 yield 语句,则程序会抛出 StopIteration 异常。举个例子:
def foo(): try: yield 1 except ValueError: print('捕获到 ValueError') f = foo() print(next(f)) f.throw(ValueError)程序执行结果为:
1
捕获到 ValueError
Traceback (most recent call last):
File "D:\python3.6\1.py", line 9, in <module>
f.throw(ValueError)
StopIteration
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算