Python Glossary English

все Python 3Итераторы и генераторыпонятие

Протокол итератора

протокол итератора

Итератор — объект с __iter__ и __next__. __next__ возвращает следующее значение или поднимает StopIteration.

Синтаксис

class Iter:
    def __iter__(self): return self
    def __next__(self): ...

Не путайте итерируемое и итератор: список можно обойти сколько угодно раз, а итератор — ровно один, и после исчерпания он обязан продолжать поднимать StopIteration, а не начинать заново. Поэтому класс, у которого __iter__ возвращает self, во втором цикле for молча ничего не выдаст; чтобы объект переиспользовался, __iter__ должен возвращать каждый раз новый объект-итератор.

Примеры

class CountUp:
    def __init__(self, start, stop):
        self.current = start
        self.stop = stop
    def __iter__(self):
        return self
    def __next__(self):
        if self.current >= self.stop:
            raise StopIteration
        val = self.current
        self.current += 1
        return val
for x in CountUp(1, 4):
    print(x, end=' ')  # → 1 2 3
class Squares:
    def __init__(self, n):
        self.i = 0; self.n = n
    def __iter__(self): return self
    def __next__(self):
        if self.i >= self.n: raise StopIteration
        val = self.i**2
        self.i += 1
        return val
print(list(Squares(5)))  # → [0,1,4,9,16]
# Итератор — одноразовый!
it = iter([1,2,3])
print(list(it))  # → [1,2,3]
print(list(it))  # → [] исчерпан!
class FibIter:
    def __init__(self, max_n):
        self.a, self.b = 0, 1
        self.max_n = max_n
    def __iter__(self): return self
    def __next__(self):
        if self.a > self.max_n: raise StopIteration
        val = self.a
        self.a, self.b = self.b, self.a+self.b
        return val
print(list(FibIter(50)))  # → [0,1,1,2,3,5,8,13,21,34]
# for цикл использует __iter__/__next__
lst = [10, 20, 30]
it = iter(lst)
while True:
    try:
        print(next(it))
    except StopIteration:
        break  # → 10 20 30
class Reversed:
    def __init__(self, data):
        self.data = data
        self.i = len(data) - 1
    def __iter__(self): return self
    def __next__(self):
        if self.i < 0: raise StopIteration
        val = self.data[self.i]
        self.i -= 1
        return val
print(list(Reversed([1,2,3,4])))  # → [4,3,2,1]

См. также

Открыть в полном глоссарииdocs.python.orgСообщить о неточности