Python迭代器中的hasNext?

Jua*_*nti 141 python iterator

有没有Python迭代器得到一个hasNext方法?

Der*_*ang 201

有一个替代StopIteration使用next(iterator, default_value).

为了exapmle:

>>> a = iter('hi')
>>> print next(a, None)
h
>>> print next(a, None)
i
>>> print next(a, None)
None
Run Code Online (Sandbox Code Playgroud)

因此None,如果不需要异常方式,则可以检测迭代器结尾的其他预先指定的值.

  • 如果你使用None作为"哨兵",你最好确保你的迭代器没有任何Nones.你也可以做`sentinel = object()`和`next(iterator,sentinel)`并用`is`测试. (62认同)
  • 问题是,通过这种方式,您也可以使用迭代器中的下一个值。Java 中的 hasNext 不消耗下一个值。 (4认同)
  • 在@samboosalis 之后,我宁愿使用内置的`unittest.mock.sentinel` 对象,它允许你编写一个显式的`next(a, sentinel.END_OF_ITERATION)` 然后`if next(...) == sentinel.END_OF_ITERATION ` (2认同)

ava*_*kar 93

不,没有这样的方法.迭代的结束由异常指示.请参阅文档.

  • "请求宽恕比允许更容易.":检查迭代器是否具有下一个元素并不是要求许可.在某些情况下,您希望测试是否存在下一个元素而不使用它.我会接受try catch解决方案,如果有一个`unnext()`方法在我通过调用`next()`检查它存在之后将第一个元素放回去. (99认同)
  • "要求宽恕比获得许可更容易." (65认同)
  • @Giorgio,没有办法知道是否存在另一个元素而不执行生成它的代码(你不知道生成器是否会执行`yield`).当然,编写一个存储`next()`结果的适配器并提供`has_next()`和`move_next()`并不困难. (12认同)
  • 可以使用相同的想法来实现`hasNext()`方法(生成,缓存并在成功时返回true,或在失败时返回false).然后`hasNext()`和`next()`都依赖于一个共同的底层`getNext()`方法和缓存项.我真的不明白为什么`next()`不应该在标准库中,如果它很容易实现提供它的适配器. (5认同)
  • @LarsH:你的意思是一个迭代器,它从一个可以在读取时更改的文件中读取?我同意这可能是一个问题(它会影响任何提供`next()`和`hasNext()`方法的库,而不仅仅是假设的Python库.所以,是的,当读取**元素时,如果被扫描的流的内容依赖于**,则`next()`和`hasNext()`变得棘手. (2认同)

Ale*_*lli 36

如果你真的需要一个has-next功能(因为你只是忠实地从Java中的参考实现转录的算法,说,还是因为你写一个原型,需要轻松转录到Java的时候,它的完成),它很容易用一个小包装类获得它.例如:

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
Run Code Online (Sandbox Code Playgroud)

现在像

x = hn_wrapper('ciao')
while x.hasnext(): print next(x)
Run Code Online (Sandbox Code Playgroud)

发射

c
i
a
o
Run Code Online (Sandbox Code Playgroud)

按要求.

请注意,使用next(sel.it)内置需要Python 2.6或更高版本; 如果你使用的是旧版本的Python,请self.it.next()改用(next(x)在示例用法中类似).[[你可能会合理地认为这个说明是多余的,因为Python 2.6已经存在了一年多了 - 但是当我在回复中使用Python 2.6功能时,一些评论者或其他人认为有义务指出他们 2.6的功能,因此我试图阻止这样的评论一次;-)]]

  • "忠实地从Java中的参考实现转录算法"是需要`has_next`方法的最糟糕的理由.Python的设计使得不可能使用`filter`来检查数组是否包含与给定谓词匹配的元素.Python社区的傲慢和短视是惊人的. (3认同)
  • @JonathanCast 不确定我是否遵循。在 Python 中,你通常会使用 `map` 和 `any` 代替 `filter`,但你可以使用 `SENTINEL = object(); next(filter(predicate, arr), SENTINEL) 不是 SENTINEL` 或者忘记了 `SENTINEL`,只需使用 `try: except` 并捕获 `StopIteration`。 (3认同)

Bri*_*per 13

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

>>> it = iter("hello")
>>> for i in it:
...     print i
...
h
e
l
l
o
Run Code Online (Sandbox Code Playgroud)


juj*_*juj 7

从任何迭代器对象尝试__length_hint __()方法:

iter(...).__length_hint__() > 0
Run Code Online (Sandbox Code Playgroud)

  • 合法的问题!通常它是由内置函数公开的方法的语法(例如len,实际上是调用__len__).length_hint不存在这样的内置函数,但实际上它是一个待定的提议(PEP424). (6认同)
  • 我总是想知道为什么地球上的python有__ xxx __方法?他们看起来很难看. (4认同)

syk*_*ora 6

您可以tee使用 ,itertools.tee和检查StopIterationteed 迭代器的迭代器。


mik*_*iku 5

hasNext有点转化为StopIteration例外,例如:

>>> it = iter("hello")
>>> it.next()
'h'
>>> it.next()
'e'
>>> it.next()
'l'
>>> it.next()
'l'
>>> it.next()
'o'
>>> it.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
Run Code Online (Sandbox Code Playgroud)