python--基础知识点--generator

1. generator.next()、generator.send(value)

  generator.next():开始执行一个generator函数或者从上次执行yield表达式的地方从新开始执行generator函数。当generator函数通过next()函数继续执行时,当前的yield表达式总得值总是None。此时,这个generator函数继续执行到下一个yield表达式的地方,然后挂起,同时将yield表达式的值返回。如果generator函数后面如果没有yield表达式了,就抛出一个StopIteratio。
  generator.send(value):继续执行一个generator函数。当generator函数通过send()函数继续执行时,value这个参数变成了当前的yield表达式的值。此时,这个generator函数继续执行到下一个yield表达式的地方,然后挂起,同时将yield表达式的值返回。如果generator函数后面没有yield了,会抛出StopIteration异常。当调用send()来启动generator的时候,value这个参数必须是None,因为这个时候没有yield表达式来接受参数。

def gen_fun():
    yield 1
    print(11)
    a = yield 2
    print(a)
    yield (3)
    print(31)
    return "success"


if __name__ == '__main__':
    gen = gen_fun()
    print(next(gen))
    print(next(gen))
    a = 5
    print(gen.send(a))
    try:
        print(next(gen))
    except StopIteration as e:
        print(e.value)
	

"""
运行结果:
1
11
2
5
3
31
success
"""

"""
next(): 开始执行一个generator函数或者从上次执行yield表达式的地方从新开始执行generator函数。当
		generator函数通过next()函数继续执行时,当前的yield表达式总得值总是None。此时,这个generator
		函数继续执行到下一个yield表达式的地方,然后挂起,同时将yield表达式的值返回。如果generator函数
		后面如果没有yield表达式了,就抛出一个StopIteratio。
send(): 继续执行一个generator函数。当generator函数通过send()函数继续执行时,value这个参数变成了当前
		的yield表达式的值。此时,这个generator函数继续执行到下一个yield表达式的地方,然后挂起,同时将
		yield表达式的值返回。如果generator函数后面没有yield了,会抛出StopIteration异常。当调用send()
		来启动generator的时候,value这个参数必须是None,因为这个时候没有yield表达式来接受参数。
"""

"""
获取生成器返回结果必须进行异常处理。
"""
2. generator.throw(type[, value[, traceback]])

yield 在生成器中可以接收到通过 gen.throw() 抛出的异常,并且会将这个异常抛出到生成器的调用方。具体来说,当调用 gen.throw() 方法并传入一个异常时,生成器会在当前的 yield 语句处抛出这个异常。

这样的机制可以让生成器和调用方之间进行异常的交互,使得生成器可以处理调用方发送过来的异常,也可以根据需要选择是否继续执行或结束生成器。

以下是一个示例代码,演示了如何在生成器中通过 yield 抛出通过 gen.throw() 传入的异常:

def my_generator():
    while True:
        try:
            value = yield
            print("Received value:", value)
        except ValueError as e:
            print("Caught ValueError in generator:", e)
            # 可以在这里做一些处理,然后决定是否继续生成器的执行
            # 如果不想继续生成器的执行,可以使用 raise 语句将异常再次抛出
            raise

gen = my_generator()
next(gen)  # 启动生成器

try:
    gen.throw(ValueError("Custom error message"))
except StopIteration:
    print("Generator has finished")
3. generator.close()

  generator.close():在生成器函数挂起的地方抛出一个 GeneratorExit 异常。这并不等价于 generator.throw(GeneratorExit),后面会说原因。
  如果生成器抛出 StopIteration 异常(不管是由于正常退出还是因为该生成器已经关闭),或者抛出 GeneratorExit 异常(不捕获该异常即可),close 方法不传递该异常,直接返回到调用方。而生成器抛出的其他异常会传递给调用方。
  GeneratorExit 异常的产生意味着生成器对象的生命周期已经结束,因此生成器方法后续语句中不能再有 yield,否则会产生 RuntimeError。(而 throw 方法是期待一个 yield 返回值的,如果没有,则会抛出 StopIteration 异常。)
  对于已经正常退出或者因为异常退出的生成器对象,close 方法不会进行任何操作。

(i) 不捕获 GeneratorExit 异常,close 方法返回调用方,不传递该异常。
def gen():
    print('下面 yield 1')
    yield 1
    print('下面 yield 2')
    yield 2

g = gen()
next(g)
g.close()


"""
运行结果:
下面 yield 1
"""

print()
next(g)


"""
运行结果:
Traceback (most recent call last):
  File "test.py", line 15, in <module>
    next(g)
StopIteration
"""

"""
注意:对已经关闭的生成器对象使用 next 会抛出 StopIteration 异常。
"""
(ii) 生成器自然退出抛出 StopIteration 异常,该异常不会传递给调用方,close 方法正常返回。
def gen():
    try:
        yield 1
    except GeneratorExit:
        print('捕获到GeneratorExit')
    print('生成器函数结束了')

g = gen()
print(next(g))
g.close()


"""
运行结果:
1
捕获到GeneratorExit
生成器函数结束了
"""
(iii) 在 GeneratorExit 抛出后还有 yield 语句,会产生 RuntimeError。另外生成器对象被垃圾回收时,解释器会自动调用该对象的 close 方法(PEP 342),这意味着最好不要在相应的 except 和 finally 中写 yield 语句,否则不知道什么时候就会抛出 RuntimeError 异常。
def gen():
    try:
        yield 1
    except GeneratorExit:
        print('捕获到 GeneratorExit')
        print('尝试在 GeneratorExit 产生后 yield 一个值')
        yield 2

    print('生成器结束')


g = gen()
next(g)
g.close()


"""
运行结果:
捕获到 GeneratorExit
尝试在 GeneratorExit 产生后 yield 一个值
Traceback (most recent call last):
  File "test.py", line 14, in <module>
    g.close()
RuntimeError: generator ignored GeneratorExit
"""

一种防止抛出 RuntimeError 的安全生成器写法:设置一个布尔标识。

def safegen():
    yield 'so far so good'
    closed = False
    try:
        yield 'yay'
    except GeneratorExit:
        closed = True
        raise
    finally:
        if not closed:
            yield 'boo'
(iv) 对已经关闭的生成器对象调用 close() 方法,不会进行任何操作。
def gen():
    yield 1
    print('我不会被执行')
    print('因为在 yield 1 就抛出了 GeneratorExit 异常')
    print('未经捕获的 GeneratorExit 异常不会传递')
    print('返回执行权给 close 的调用方')

g = gen()
g.close()
g.close()
g.close()  # 多次调用 close,什么效果都没有

补充:GeneratorExit 异常只有在生成器对象被激活后,才有可能产生。

def gen():
    try:
        yield 1
    except GeneratorExit:
        print('捕获到 GeneratorExit')
        raise


g1 = gen()
next(g1)
g1.close()


"""
运行结果:
捕获到 GeneratorExit
"""

# 没有激活生成器,就不会触发 GeneratorExit 异常
print()
g2 = gen()
g2.close()
print('脚本运行完毕')


"""
运行结果:
脚本运行完毕
"""


[参考博客]https://blog.csdn.net/jpch89/article/details/87036970
     http://blog.chinaunix.net/uid-17260303-id-2811335.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值