Python迭代器有has_next方法吗?


当前回答

也可以实现一个helper生成器,它包装任何迭代器,并回答问题,如果它有next值:

在网上试试!

def has_next(it):
    first = True
    for e in it:
        if not first:
            yield True, prev
        else:
            first = False
        prev = e
    if not first:
        yield False, prev

for has_next_, e in has_next(range(4)):
    print(has_next_, e)

输出:

True 0
True 1
True 2
False 3

该方法的主要缺点(可能也是唯一的缺点)是它会多预读一个元素,对于大多数任务来说,它是完全可以的,但对于某些任务,它可能是不允许的,特别是如果has_next()的用户没有意识到这种预读逻辑,可能会误用它。

上面的代码也适用于无限迭代器。

实际上,对于所有的情况下,我曾经编写这样的has_next()是完全足够的,没有造成任何问题,事实上是非常有用的。你只需要知道它的预读逻辑。

其他回答

不,没有这样的方法。迭代的结束由异常表示。请参见文档。

非常有趣的问题,但是这个“hasnext”的设计已经放进了leetcode: https://leetcode.com/problems/iterator-for-combination/

这是我的实现:

class CombinationIterator:

def __init__(self, characters: str, combinationLength: int):
    from itertools import combinations
    from collections import deque
    self.iter = combinations(characters, combinationLength)
    self.res = deque()


def next(self) -> str:
    if len(self.res) == 0:
        return ''.join(next(self.iter))
    else:
        return ''.join(self.res.pop())


def hasNext(self) -> bool:
    try:
        self.res.insert(0, next(self.iter))
        return True
    except:
        return len(self.res) > 0

使用next(迭代器,default_value)可以替代StopIteration。

For exapmle:

>>> a = iter('hi')
>>> print next(a, None)
h
>>> print next(a, None)
i
>>> print next(a, None)
None

因此,如果你不想用异常方式,你可以为None或其他预先指定的值检测迭代器的end。

引导我进行搜索的用例如下

def setfrom(self,f):
    """Set from iterable f"""
    fi = iter(f)
    for i in range(self.n):
        try:
            x = next(fi)
        except StopIteration:
            fi = iter(f)
            x = next(fi)
        self.a[i] = x 

hasnext()在哪里可用

def setfrom(self,f):
    """Set from iterable f"""
    fi = iter(f)
    for i in range(self.n):
        if not hasnext(fi):
            fi = iter(f) # restart
        self.a[i] = next(fi)

这对我来说更干净。显然,您可以通过定义实用程序类来解决这些问题,但接下来的情况是,您有20多种几乎等效的解决方法,每种方法都有各自的怪癖,如果您希望重用使用不同解决方法的代码,那么您必须在单个应用程序中有多个几乎等效的代码,或者四处挑选并重写代码以使用相同的方法。“只做一次,就把它做好”的格言很失败。

此外,迭代器本身需要有一个内部的“hasnext”检查,以查看是否需要引发异常。然后,这个内部检查被隐藏起来,因此需要通过尝试获取一个项、捕捉异常并在抛出异常时运行处理程序来测试它。在我看来,这是不必要的隐藏。

不。最类似的概念很可能是StopIteration异常。