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


Answers

Существует альтернатива 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 или другого заранее заданного значения для конца итератора, если вы не хотите использовать способ исключения.

Question

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




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 цикл Python for for просто делает то, что вы хотите:

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



То, как я решил свою проблему, состоит в том, чтобы сохранить счетчик количества объектов, которые повторялись до сих пор. Я хотел выполнить итерацию по набору, используя вызовы метода экземпляра. Поскольку я знал длину набора и количество элементов, подсчитанных до сих пор, у меня фактически был метод 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

Конечно, пример - игрушечный, но вы получаете идею. Это не будет работать в тех случаях, когда нет возможности получить длину итерации, например, генератора и т. Д.




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

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




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




Related