欢迎来到赛兔子家园

Python生成器(send,close,throw)方法详解

Python生成器的send、close和throw方法‌是用于控制生成器执行流程的重要工具。生成器是迭代器的一种,通过yield关键字实现,它能够在每次迭代时按需生成值,从而节省内存。

1‌、send方法‌:send方法可以向生成器发送一个值,并使生成器继续执行到下一个yield表达式。与next()方法不同,send方法可以在生成器与调用者之间实现双向通信。使用send方法时,如果生成器内部有yield表达式接收值,则发送的值会被赋值给该yield表达式的左侧。如果发送的是None,则send方法的功能与next()相同‌。
‌2、throw方法‌:throw方法用于向生成器内部抛出一个异常,生成器内部可以捕获并处理该异常。如果生成器内部没有捕获这个异常,它将传播到调用者,并终止生成器。这为生成器提供了处理异常的机制‌
3‌、close方法‌:close方法用于关闭一个生成器对象。调用close方法后,生成器将抛出GeneratorExit异常,之后不能再对生成器执行任何方法,否则会抛出StopIteration异常。这标志着生成器生命周期的结束‌

通过这些方法,Python生成器提供了灵活的控制流程和异常处理机制,适用于需要按需生成数据、节省内存的场景‌

send()

这里重点讲解一些带参数的 send(value) 的用法,其具备next() 函数的部分功能,即将暂停在 yield 语句出的程序继续执行,但与此同时,该函数还会将 value 值作为 yield 语句返回值赋值给接收者。
注意,带参数的 send(value) 无法启动执行生成器函数。也就是说,程序中第一次使用生成器调用 next() 或者 send() 函数时,不能使用带参数的 send() 函数。

示例:

def foo():
    a = yield "你好"
    b = yield a
    yield b

f = foo()
print(f.send(None))
print(f.send("青牛Python学院"))
print(f.send("https://home.cnblogs.com/u/qingchengzi"))

分析执行流程:

1、首先,构建生成器函数,并创建生成器对象f
2、使用生成器f调用无参的send()函数,其功能和 next()函数完全相同,因此开始执行生成器函数,即执行到第一个 yield "你好" 语句,该语句会返回 "你好" 字符串,然后程序停止到此处(注意,此时还未执行对a的赋值操作)
3、下面开始使用生成器f调用有参的send()函数,首先它会将暂停的程序开启,同时还会将其参数“青牛Python学院”赋值给当前yield语句的接收者,也就是a变量。程序一直执行完 yield a 再次暂停,因此会输出“青牛Python学院”。
4、最后依旧是调用有参的send()函数,同样它会启动餐厅的程序,同时将参数“https://home.cnblogs.com/u/qingchengzi”传给 b,然后执行完 yield b 后(输出 https://home.cnblogs.com/u/qingchengzi),程序执行再次暂停。

程序执行结果:

你好
青牛Python学院
https://home.cnblogs.com/u/qingchengzi

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

f = foo()
print(next(f))
f.close()

程序执行结果:

1
捕获到GeneratorExit
Traceback (most recent call last):
  File "E:/workbook/Python平时练习学习目录/测试代码用.py", line 310, in <module>
    f.close()
RuntimeError: generator ignored GeneratorExit

另外,生成器函数一旦使用 close() 函数停止运行,后续将无法再调用 next() 函数或者 __next__() 方法启动执行,否则会抛出 StopIteration 异常。

例如:

def foo():
    yield "https://home.cnblogs.com/u/qingchengzi"
   print("生成器停止执行")

f = foo()
print(next(f)) #输出:https://home.cnblogs.com/...
f.close()
next(f) # 原本应输出"生成器停止执行"

运行结果:

https://home.cnblogs.com/u/qingchengzi
  File "E:/workbook/Python平时练习学习目录/测试代码用.py", line 320, 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 "E:/workbook/Python平时练习学习目录/测试代码用.py", line 329, in <module>
    f.throw(ValueError)
StopIteration

显然,一开始生成器函数在 yield 1 处暂停执行,当执行 throw() 方法时,它会先抛出 ValueError 异常,然后继续执行后续代码找到下一个 yield 语句,该程序中由于后续不再有 yield 语句,因此程序执行到最后,会抛出一个 StopIteration 异常。

 

posted on 2024-10-08 09:33  赛兔子  阅读(215)  评论(0)    收藏  举报

导航