【问题标题】:Python unexpected StopIterationPython 意外的 StopIteration
【发布时间】:2014-09-25 23:39:06
【问题描述】:

这是我的代码

class A:
    pass

def f():
    yield A()

def g():
    it = f()
    next(it).a = next(it, None)

g()

产生StopIteration 错误,由next(it).a = next(it, None) 引起。为什么?

文档说如果提供了默认值,next 函数不会引发 StopIteration,我希望它能够从生成器中获取第一个项目(A 实例)并设置 @987654328 @ 属性为None

【问题讨论】:

    标签: python generator next assign operator-precedence


    【解决方案1】:

    您的 f() 生成器函数只产生 一个 值。之后它耗尽并引发StopIteration

    >>> class A:
    ...     pass
    ... 
    >>> def f():
    ...     yield A()
    ... 
    >>> generator = f()
    >>> generator
    <generator object f at 0x10be771f8>
    >>> next(generator)
    <__main__.A object at 0x10be76f60>
    >>> next(generator)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    

    那是因为在f()没有循环 可以产生不止一次,生成器函数本身不会循环,只是因为你可以在中使用它 em> 一个循环。

    请注意,对于赋值,Python 会先执行右侧表达式,然后再确定将其分配给 的内容。所以next(it, None)首先被调用,分配的next(it).a被调用second

    f() 函数的主体与任何其他 Python 函数一样执行,但添加了 pausing。生成器上的next() 取消暂停代码,然后代码运行直到执行下一个yield 语句。然后该语句再次暂停生成器。如果函数改为结束(返回),则引发StopIteration

    在您的 f() 生成器中,这意味着:

    1. 当您调用f() 时,会创建一个新的生成器对象。函数体已暂停。
    2. 你第一次打电话给next()。代码开始运行,创建A() 的实例并生成该实例。该功能再次暂停。
    3. 您再次致电next()。代码开始运行,到达函数末尾,然后返回。 StopIteration 被提出。

    如果您向f() 添加一个循环,或者只是添加一个 yield 行,您的代码就可以工作:

    def f():
        yield A()
        yield A()
    

    def f():
        while True:
            yield A()
    

    【讨论】:

      【解决方案2】:

      因为f 只产生一个值,所以您只能对其调用一次next

      表达式的右侧 (next(it, None)) 在左侧计算之前,因此会耗尽生成器。

      在左侧跟注next(it).a 之后会加注StopIteration

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-20
        • 2021-12-22
        • 2023-04-09
        • 1970-01-01
        • 2017-12-27
        • 2016-08-05
        • 1970-01-01
        • 2018-10-08
        相关资源
        最近更新 更多