• 协程之生成器


    def gen_fun():
        #1. 可以产出值, 2. 可以接收值(调用方传递进来的值)
        html = yield  "http://projectsedu.com"
        print(html)
        yield 3
        yield 4
        yield 5
        return 'sunlong'
    
    #1. 生成器不只可以产出值,还可以接收值
    if __name__ == "__main__":
        gen = gen_fun()
        #在调用send发送非none值之前,我们必须启动一次生成器, 方式有两种1. gen.send(None), 2. next(gen)
        url = gen.send(None)
        print(url)
        html = 'sunlong88'
        #send方法可以传递值进入生成器内部,同时还可以重启生成器执行到下一个yield位置
        print(gen.send(html))
        print(next(gen))
        print(next(gen))
        #执行最后一个 找不到数据就会报错 StopIteration: sunlong
        print(next(gen))

     执行结果:

    Traceback (most recent call last):
      File "E:/pythoncode/day07/04.py", line 17, in <module>
        print(next(gen))
    StopIteration: sunlong
    http://projectsedu.com
    sunlong88
    3
    4
    5
    
    进程已结束,退出代码1
    

      

    终止协程和异常处理:

    close:

    def gen_func():
        #1. 可以产出值, 2. 可以接收值(调用方传递进来的值)
        try:
            yield "http://projectsedu.com"
        except GeneratorExit :
            pass
            # raise StopIteration
        yield 2
        yield 3
        return "sunlong"
    
    if __name__ == "__main__":
        gen = gen_func()
        print(next(gen))
        gen.close()
        # print("sunlong88")
        # print(next(gen))
    
    执行结果:
    
    http://projectsedu.com
    Traceback (most recent call last):
      File "E:/pythoncode/day07/04.py", line 22, in <module>
        gen.close()
    RuntimeError: generator ignored GeneratorExit
    def gen_func():
        #1. 可以产出值, 2. 可以接收值(调用方传递进来的值)
        try:
            yield "http://projectsedu.com"
        except GeneratorExit :
            pass
            # raise StopIteration
        # yield 2
        # yield 3
        return "sunlong"
    
    if __name__ == "__main__":
        gen = gen_func()
        print(next(gen))
        gen.close()
        # print("sunlong88")
        # print(next(gen))

    上述代码中,注释了其他yield  ,再次执行就不会有异常了

    http://projectsedu.com
    
    进程已结束,退出代码0
    

      

    或者捕获异常,并抛出StopIteration异常(表示已经运行到结尾了),这样也不会有报错

    def gen_func():
        #1. 可以产出值, 2. 可以接收值(调用方传递进来的值)
        try:
            yield "http://projectsedu.com"
        except GeneratorExit :
            # pass
            raise StopIteration
        yield 2
        yield 3
        return "sunlong"
    
    if __name__ == "__main__":
        gen = gen_func()
        print(next(gen))
        gen.close()
        # print("sunlong88")
        # print(next(gen))

    总结close:

    #gen.close() 致使生成器在暂停的yield表达式处抛出GeneratorExit异常。如果生成器处没有处理这个异常,
    或者抛出StopIterration异常(运行到结尾),调用方不会报错。
    如果收到GeneratorExit异常,生成器一定不能产出值,否则解释器会抛出RuntimeError异常,
    生成器抛出的其他异常会向上冒泡,传给调用方
    (要么不要去捕获异常,如果捕获了异常那么那么就请你抛出StopIterration异常(表示已经到了结尾了))

    throw:

    向生成器抛一个异常:

    def gen_func():
        #1. 可以产出值, 2. 可以接收值(调用方传递进来的值)
        yield "http://projectsedu.com"
        yield 2
        yield 3
        return "bobby"
    
    if __name__ == "__main__":
        gen = gen_func()
        print(next(gen))
        print(gen.throw(Exception, "download error"))
    
    执行结果:
        http://projectsedu.com
        Exception: download error

    改进一下(生成器自己捕获异常):

    def gen_func():
        #1. 可以产出值, 2. 可以接收值(调用方传递进来的值)
        try:
            yield "http://projectsedu.com"
        except Exception as e:
            pass
        yield 2
        yield 3
        return "bobby"
    
    if __name__ == "__main__":
        gen = gen_func()
        print(next(gen))
        print(gen.throw(Exception, "download error"))
    
    执行结果:
        http://projectsedu.com
        2

    总结:

    throw会使生成器在暂停的yield表达式处抛出指定的异常,如果生成器处理了抛出的异常,

    代码会向前执行到下一个yield表达式。而产生的值会成为调用throw方法得到的返回值,如果生成器没有处理抛出的异常,异常会向上冒泡,

    传到调用方的上下文中

  • 相关阅读:
    49 我素故我在
    91 棋盘游戏
    55 删除数组重复元素
    54 删除数组元素
    C++虚函数, 纯虚函数
    iOS-OC-多态
    C++函数引用形参和非引用形参
    怎么清理Mac 硬盘里的其他
    Vue.js中this.$nextTick()的使用
    data中有嵌套,取值要链式取
  • 原文地址:https://www.cnblogs.com/sunlong88/p/9493981.html
Copyright © 2020-2023  润新知