it-swarm.com.ru

hasNext в итераторах Python?

Разве итераторы Python не получили метод hasNext?

117
Juanjo Conti

Нет, такого метода нет. Конец итерации обозначен исключением. Смотрите документацию .

78
avakar

Существует альтернатива StopIteration с использованием next(iterator, default_value).

Например:

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

Таким образом, вы можете определить None или другое предварительно заданное значение для конца итератора, если вы не хотите использовать метод исключения.

166
Derrick Zhang

Если вам действительно нужна функциональность 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, поэтому я пытаюсь предупредить такие комментарии на этот раз ;-)]]

31
Alex Martelli

В дополнение ко всем упоминаниям StopIteration цикл Python for просто делает то, что вы хотите:

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

Попробуйте метод __length_hint __ () из любого объекта итератора:

iter(...).__length_hint__() > 0
8
juj

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
5
miku

Нет. Наиболее похожая концепция, скорее всего, является исключением StopItered.

3
James Thompson

Вы можете tee итератор, используя itertools.tee, и проверьте StopIteration на итераторе teed.

3
sykora

Я полагаю, что в python просто есть next () и, согласно документу, он выдает исключение, если больше нет элементов.

http://docs.python.org/library/stdtypes.html#iterator-types

2
Charles

Вариант использования, который привел меня к поиску этого заключается в следующем

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, чтобы увидеть, нужно ли ему вызывать исключение. Эта внутренняя проверка затем скрывается, поэтому ее необходимо протестировать, пытаясь получить элемент, перехватить исключение и запустить обработчик, если он был сгенерирован. Это ненужное сокрытие ИМО.

1
John Allsup

Рекомендуемый путь - 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()
0
Ramin Darvishov

хороший подход для такого вопроса/проблем - проверить, что у нас есть в dir (объект/метод/итератор/тип/класс/...)

вы увидите, что dir(iterator) return __length_hint__

и iterator.__length_hint__() положителен до конца итерации.

вот и все.

0
Sławomir Lenart