【问题标题】:is there an alternative way of calling next on python generators?在 python 生成器上调用 next 是否有另一种方法?
【发布时间】:2010-10-04 18:35:56
【问题描述】:

我有一个生成器,我想知道是否可以使用它而不必担心 StopIteration ,我想在没有 for item in generator 的情况下使用它。例如,我想将它与 while 语句(或其他构造)一起使用。我怎么能这样做?

【问题讨论】:

    标签: python language-features


    【解决方案1】:

    用它来包装你的生成器:

    class GeneratorWrap(object):
    
          def __init__(self, generator):
              self.generator = generator
    
          def __iter__(self):
              return self
    
          def next(self):
              for o in self.generator:
                  return o
              raise StopIteration # If you don't care about the iterator protocol, remove this line and the __iter__ method.
    

    像这样使用它:

    def example_generator():
        for i in [1,2,3,4,5]:
            yield i
    
    gen = GeneratorWrap(example_generator())
    print gen.next()  # prints 1
    print gen.next()  # prints 2
    

    更新:请使用下面的答案,因为它比这个更好。

    【讨论】:

    • 当我第六次调用它时会发生什么?
    • @Tsunami,我还应该提到,可以通过在 next() 方法的 for 循环下方添加另一个 return 语句来更改此行为。生成器耗尽后,无论您返回什么,它都将是默认值。
    • 对了,你能解释一下iter中返回self的逻辑是什么吗?
    • 如果您不想要迭代器,请不要使用它。在这种情况下,如果您的对象不是迭代器,请不要为方法使用 next 名称。叫它别的东西,例如safe_next(self, sentinel=None) 方法 -- 返回 sentinel 而不是抛出 StopIteration。内置next() 功能不同。
    • 该方法的更好名称是next_noraise()。更好的是使用@SilentGhost 的建议。
    【解决方案2】:

    另一种选择是一次读取所有生成器值:

    >>> alist = list(agenerator)
    

    例子:

    >>> def f():
    ...   yield 'a'
    ...
    >>> a = list(f())
    >>> a[0]
    'a'
    >>> len(a)
    1
    

    【讨论】:

    • @hasen: list[index] 不会引发 StopIteration。它可以在没有for 循环的情况下使用。它可以与while 循环一起使用。问题中的所有条件均已满足。
    • 虽然我认为@SilentGhost 的方法更好。
    • 只要@Torsten Marek 从 itertools.count() 获得 StopIteration,我就会读取所有值。 :) OP 只询问可以产生 StopIteration 的生成器,因此无限生成器不适用。
    【解决方案3】:

    内置函数

    下一个(迭代器[,默认])
    通过调用 __next__() 方法从迭代器中检索下一项。如果给出默认值,则在迭代器耗尽时返回,否则引发 StopIteration。

    在 Python 2.5 及更早版本中:

    raiseStopIteration = object()
    def next(iterator, default=raiseStopIteration):
        if not hasattr(iterator, 'next'):
           raise TypeError("not an iterator")
        try:
           return iterator.next()
        except StopIteration:
            if default is raiseStopIteration:
               raise
            else:
               return default
    

    【讨论】:

    • 我为 Python 2.5 添加了 next() 实现
    猜你喜欢
    • 2012-01-30
    • 2014-12-13
    • 1970-01-01
    • 2020-06-18
    • 2018-01-10
    • 2022-12-24
    • 2017-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多