账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    在 python3 yield from 中,抛出 StopIteration 异常的条件是什么?
    26
    0

    个人理解:
    调用方 .send(None) 后,在 子生成器 break 时抛出 StopIteration 异常,return 返回值后在委托生成器中赋值给 yield from 表达式左侧变量并捕捉 子生成器 抛出的 StopIteration 异常。

    问题:
    但是为什么此时如果 委托生成器 没有 while True: ,又会抛出 StopIteration 异常?
    原代码:

    # 子生成器
    def average_gen():
        total = 0
        count = 0
        average = 0
        while True:
            new_num = yield average
            if new_num is None:
                break
            count += 1
            total += new_num
            average = total/count
    
        # 每一次return,都意味着当前协程结束。
        return total,count,average
    
    # 委托生成器
    def proxy_gen():
        while True:
            # 只有子生成器要结束(return)了,yield from左边的变量才会被赋值,后面的代码才会执行。
            total, count, average = yield from average_gen()
            print("计算完毕!!\n总共传入 {} 个数值, 总和:{},平均数:{}".format(count, total, average))
    
    # 调用方
    def main():
        calc_average = proxy_gen()
        next(calc_average)            # 预激协程
        print(calc_average.send(10))  # 打印:10.0
        print(calc_average.send(20))  # 打印:15.0
        print(calc_average.send(30))  # 打印:20.0
        calc_average.send(None)      # 结束协程
        # 如果此处再调用calc_average.send(10),由于上一协程已经结束,将重开一协程
    
    if __name__ == '__main__':
        main()
        

    委托生成器 中 while True: 的作用是什么呢?
    为什么去掉 委托生成器 的 while True: 会抛出 StopIteration 异常呢?
    或者说,为什么在 委托生成器 中加上 while True: 就不会抛出 StopIteration 异常了呢?
    修改后的代码:

    # 子生成器
    def average_gen():
        total = 0
        count = 0
        average = 0
        while True:
            new_num = yield average
            if new_num is None:
                break
            count += 1
            total += new_num
            average = total/count
    
        # 每一次return,都意味着当前协程结束。
        return total,count,average
    
    # 委托生成器
    def proxy_gen():
        # while True:
            # 只有子生成器要结束(return)了,yield from左边的变量才会被赋值,后面的代码才会执行。
            total, count, average = yield from average_gen()
            print("计算完毕!!\n总共传入 {} 个数值, 总和:{},平均数:{}".format(count, total, average))
    
    # 调用方
    def main():
        calc_average = proxy_gen()
        next(calc_average)            # 预激协程
        print(calc_average.send(10))  # 打印:10.0
        print(calc_average.send(20))  # 打印:15.0
        print(calc_average.send(30))  # 打印:20.0
        calc_average.send(None)      # 结束协程
        # 如果此处再调用calc_average.send(10),由于上一协程已经结束,将重开一协程
    
    if __name__ == '__main__':
        main()

    异常信息:

    10.0
    15.0
    20.0
    计算完毕!!
    总共传入 3 个数值, 总和:60,平均数:20.0
    Traceback (most recent call last):
      File "f:\VSCodeSC\python\tempCodeRunnerFile.python", line 35, in <module>
        main()
      File "f:\VSCodeSC\python\tempCodeRunnerFile.python", line 31, in main
        calc_average.send(None)      # 结束协程
    StopIteration
    1
    打赏
    收藏
    点击回答
        全部回答
    • 0
    • 无就将法 普通会员 1楼

      在 Python 3 中,yield from 是一个生成器表达式,用于简化代码并允许迭代器类。它由三个部分组成:一个表达式,一个 yield 语句,和一个可迭代对象。

      在这个表达式中,我们可以包含任何生成器表达式,这将生成一个可迭代对象。yield 语句在表达式内部使用,并在 yield 语句块之后暂停。

      如果在 yield 语句块中抛出 StopIteration 异常,那么在 yield 语句块之前,整个表达式就会停止。这就是在 Python 3 中为什么yield from可以在遇到 StopIteration 异常时停止的原因为何。

      例如:

      ```python def counter(start=0): while True: yield start start += 1

      print(list(counter())) ```

      这段代码会生成一个无限循环,因为 counter 函数会在每次 yield 语句块之后都递增 start 的值。如果在 yield 语句块中抛出 StopIteration 异常,那么循环就会停止。

      然而,需要注意的是,yield from 是一个生成器表达式,它不会自动处理 StopIteration 异常。在上面的代码中,如果 counter 函数在 yield 语句块中抛出 StopIteration 异常,那么这个异常将会被 counter 函数抛出,而不是由生成器表达式处理。

    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部