Python迭代器没有得到hasNext
方法吗?
答案 0 :(得分:178)
使用StopIteration
替代next(iterator, default_value)
。
exapmle:
>>> a = iter('hi')
>>> print next(a, None)
h
>>> print next(a, None)
i
>>> print next(a, None)
None
因此,如果您不想要异常方式,则可以检测迭代器结尾的None
或其他预先指定的值。
答案 1 :(得分:84)
不,没有这样的方法。迭代的结束由异常指示。请参阅documentation。
答案 2 :(得分:33)
如果你真的需要一个has-next
功能(因为你只是忠实地用Java中的参考实现转录算法,比如说,或者因为你正在写一个原型< em>将需要在完成时轻松转录为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
现在像
x = hn_wrapper('ciao')
while x.hasnext(): print next(x)
发射
c
i
a
o
根据需要。
请注意,使用next(sel.it)
作为内置函数需要Python 2.6或更高版本;如果您使用的是旧版本的Python,请使用self.it.next()
代替(在示例用法中类似于next(x)
)。 [[你可能会合理地认为这个说明是多余的,因为Python 2.6已经存在了一年多了 - 但是当我在回复中使用Python 2.6功能时,一些评论者或其他人认为有义务指出他们是 2.6的功能,因此我试图阻止这样的评论一次; - )]]
答案 3 :(得分:11)
除了所有提到的StopIteration之外,Python“for”循环只是做你想要的:
>>> it = iter("hello")
>>> for i in it:
... print i
...
h
e
l
l
o
答案 4 :(得分:7)
从任何迭代器对象中尝试__length_hint __()方法:
iter(...).__length_hint__() > 0
答案 5 :(得分: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
StopIteration
docs:http://docs.python.org/library/exceptions.html#exceptions.StopIteration 答案 6 :(得分:4)
你可以使用tee
itertools.tee
迭代器,并在teed迭代器上检查StopIteration
。
答案 7 :(得分:3)
没有。最相似的概念很可能是StopIteration exception.
答案 8 :(得分:2)
我相信python只有next(),并且根据文档,它会抛出异常,因为没有更多的元素。
答案 9 :(得分:1)
引导我搜索此内容的用例如下
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)
对我来说更清洁。显然,你可以通过定义实用程序类来解决问题,但是接下来发生的事情就是你有大量二十多种不同的几乎相同的变通方法,每种方法都有它们的怪癖,如果你想重用使用不同变通方法的代码,你必须要么在您的单个应用程序中具有多个近似等效,或者选择并重写代码以使用相同的方法。 “做一次,做得好”的格言失败了。
此外,迭代器本身需要运行内部“hasnext”检查以查看是否需要引发异常。然后隐藏此内部检查,以便需要通过尝试获取项目,捕获异常并在抛出时运行处理程序来进行测试。这是不必要的隐藏IMO。
答案 10 :(得分:0)
建议的方式是 StopIteration 。 请参阅tutorialspoint
中的斐波那契示例#!usr/bin/python3
import sys
def fibonacci(n): #generator function
a, b, counter = 0, 1, 0
while True:
if (counter > n):
return
yield a
a, b = b, a + b
counter += 1
f = fibonacci(5) #f is iterator object
while True:
try:
print (next(f), end=" ")
except StopIteration:
sys.exit()
答案 11 :(得分:0)
一个非常有趣的问题,但是这个“ 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
答案 12 :(得分:0)
也可以实现一个辅助生成器来包装任何迭代器并回答问题是否有下一个值:
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()
的所有情况,已经完全足够了,并且没有引起任何问题,而且实际上非常有帮助。您只需要了解它的预读逻辑。
答案 13 :(得分:-1)
这样的问题/问题的好方法是检查我们在dir中的内容(object / method / iterator / type / class / ...)
您会看到dir(iterator)
返回__length_hint__
和iterator.__length_hint__()
为正,直到迭代结束。
就是这样。
答案 14 :(得分:-2)
我解决问题的方法是保持迭代的对象数量,到目前为止。我想使用对实例方法的调用来迭代一个集合。由于我知道集合的长度以及到目前为止计算的项目数量,因此我实际上使用了hasNext
方法。
我的代码的简单版本:
class Iterator:
# s is a string, say
def __init__(self, s):
self.s = set(list(s))
self.done = False
self.iter = iter(s)
self.charCount = 0
def next(self):
if self.done:
return None
self.char = next(self.iter)
self.charCount += 1
self.done = (self.charCount < len(self.s))
return self.char
def hasMore(self):
return not self.done
当然,这个例子是一个玩具,但你明白了。如果没有办法获得迭代的长度,就像生成器等那样,这不会起作用。