Разве Python итераторы не получили hasNext
метод?
Разве Python итераторы не получили hasNext
метод?
Ответы:
Нет, такого метода нет. Конец итерации обозначен исключением. Смотрите документацию .
unnext()
метод, чтобы вернуть первый элемент после того, как я проверил его существование, вызвав его next()
.
yield
или нет). Конечно, нетрудно написать адаптер, который хранит результат, next()
а также предоставляет has_next()
и move_next()
.
hasNext()
метода (для создания, кэширования и возврата true при успехе или возврата false при сбое). Тогда и то hasNext()
и другое next()
будет зависеть от общего базового getNext()
метода и кэшируемого элемента. Я действительно не понимаю, почему next()
не должно быть в стандартной библиотеке, если это так легко реализовать адаптер, который обеспечивает его.
next()
и hasNext()
метод, а не только гипотетическую библиотеку Python). Так что да, next()
и hasNext()
становится сложно, если содержимое сканируемого потока зависит от того, когда элементы читаются.
Есть альтернатива StopIteration
с помощью next(iterator, default_value)
.
Например:
>>> a = iter('hi')
>>> print next(a, None)
h
>>> print next(a, None)
i
>>> print next(a, None)
None
Таким образом, вы можете обнаружить None
или другое заранее заданное значение для конца итератора, если вы не хотите использовать метод исключения.
sentinel = object()
и next(iterator, sentinel)
и проверить с is
.
unittest.mock.sentinel
объект, который позволяет вам написать явное, next(a, sentinel.END_OF_ITERATION)
а затемif next(...) == sentinel.END_OF_ITERATION
Если вам действительно нужно в 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
теперь что-то вроде
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 функции, поэтому я пытаюсь предупредить такие комментарии на этот раз ;-)]]
has_next
метод. Дизайн Python делает невозможным, скажем, использование filter
для проверки, содержит ли массив элемент, соответствующий данному предикату. Высокомерие и близорукость сообщества Python ошеломляют.
TypeError: iter() returned non-iterator
map
и any
вместо filter
, но вы можете использовать SENTINEL = object(); next(filter(predicate, arr), SENTINEL) is not SENTINEL
или забыть SENTINEL
и просто использовать try: except
и поймать StopIteration
.
В дополнение ко всем упоминаниям StopIteration цикл Python for просто делает то, что вы хотите:
>>> it = iter("hello")
>>> for i in it:
... print i
...
h
e
l
l
o
Попробуйте метод __length_hint __ () из любого объекта итератора:
iter(...).__length_hint__() > 0
__init__
и __main__
? Имхо, это немного беспорядок, независимо от того, пытаетесь ли вы оправдать это.
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
документы: http://docs.python.org/library/exceptions.html#exceptions.StopIterationНет. Наиболее похожая концепция, скорее всего, является исключением StopIteration.
Я полагаю, что в python просто есть next () и, согласно документу, он выдает исключение, если больше нет элементов.
Вариант использования, который привел меня к поиску этого заключается в следующем
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, чтобы увидеть, нужно ли ему вызывать исключение. Эта внутренняя проверка затем скрывается, поэтому ее необходимо протестировать, пытаясь получить элемент, перехватить исключение и запустить обработчик, если его сгенерировать. Это ненужное сокрытие ИМО.
Предложенный способ - 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()
Способ, которым я решил свою проблему, заключается в том, чтобы до сих пор вести подсчет количества объектов, повторяемых. Я хотел перебрать множество, используя вызовы метода экземпляра. Так как я знал длину сета и количество посчитанных предметов, у меня был эффективный 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
Конечно, пример игрушечный, но вы поняли идею. Это не будет работать в тех случаях, когда нет способа получить длину итерируемого, например, генератора и т. Д.