Python迭代器有has_next方法吗?


当前回答

我认为当你想要某种has_next功能时,有一些有效的用例,在这种情况下,你应该用定义了has_next的迭代器来装饰迭代器。

结合这个问题的答案的概念,这里是我的实现,这对我来说是一个很好的简洁的解决方案(python 3.9):

_EMPTY_BUF = object()


class BufferedIterator(Iterator[_T]):
    def __init__(self, real_it: Iterator[_T]):
        self._real_it = real_it
        self._buf = next(self._real_it, _EMPTY_BUF)

    def has_next(self):
        return self._buf is not _EMPTY_BUF

    def __next__(self) -> _T_co:
        v = self._buf
        self._buf = next(self._real_it, _EMPTY_BUF)
        if v is _EMPTY_BUF:
            raise StopIteration()
        return v

主要的区别是has_next只是一个布尔表达式,也处理None值的迭代器。

将此添加到这里的测试和示例使用的要点。

其他回答

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

为了读取所有迭代,基于处理“StopIteration”执行的解决方法非常简单:

    end_cursor = False
    while not end_cursor:
        try:
            print(cursor.next())
        except StopIteration:
            print('end loop')
            end_cursor = True
        except:
            print('other exceptions to manage')
            end_cursor = True

如果您确实需要一个has-next功能,那么使用一个小包装器类很容易获得它。例如:

class hn_wrapper(object):
  def __init__(self, it):
    self.it = iter(it)
    self._hasnext = None
  def __iter__(self): return self
  def next(self):
    if self._hasnext:
      result = self._thenext
    else:
      result = next(self.it)
    self._hasnext = None
    return result
  def hasnext(self):
    if self._hasnext is None:
      try: self._thenext = next(self.it)
      except StopIteration: self._hasnext = False
      else: self._hasnext = True
    return self._hasnext

现在就像

x = hn_wrapper('ciao')
while x.hasnext(): print next(x)

发出

c
i
a
o

是必需的。

Note that the use of next(sel.it) as a built-in requires Python 2.6 or better; if you're using an older version of Python, use self.it.next() instead (and similarly for next(x) in the example usage). [[You might reasonably think this note is redundant, since Python 2.6 has been around for over a year now -- but more often than not when I use Python 2.6 features in a response, some commenter or other feels duty-bound to point out that they are 2.6 features, thus I'm trying to forestall such comments for once;-)]]

===

对于Python3,您将进行以下更改:

from collections.abc import Iterator  # since python 3.3 Iterator is here

class hn_wrapper(Iterator):  # need to subclass Iterator rather than object
  def __init__(self, it):
    self.it = iter(it)
    self._hasnext = None
    
  def __iter__(self): 
    return self
  
  def __next__(self):        # __next__ vs next in python 2
    if self._hasnext:
      result = self._thenext
    else:
      result = next(self.it)
    self._hasnext = None
    return result
  
  def hasnext(self):
    if self._hasnext is None:
      try: 
        self._thenext = next(self.it)
      except StopIteration: 
        self._hasnext = False
      else: self._hasnext = True
    return self._hasnext

使用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。

除了所有提到的StopIteration, Python的“for”循环只是做你想要的:

>>> it = iter("hello")
>>> for i in it:
...     print i
...
h
e
l
l
o