Кастомні ітератори

Середній рівень об'єктно-орієнтованого програмування в Python

Jake Roach

Data Engineer

Ітератори

Класи, що дають проходити колекцію обʼєктів або потік даних і повертати по одному елементу

  • Подібні до list, tuple, але поводяться інакше
  • Навігація, трансформація, генерація
  • Перебираються циклом for
  • Функція next()

$$

Протокол ітератора…

# Колекція
chuck = NameIterator("Charles Carmicheal")
for letter in chuck:
    print(letter)
C
h
u
...
# Потік даних
fun_game = DiceGame(rolls=3)
next(fun_game)  # ... і так далі
4
Середній рівень об'єктно-орієнтованого програмування в Python

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

__iter__()

  • Повертає ітератор, у цьому разі посилання на себе
  • ... return self

$$

__next__()

  • Повертає наступне значення з колекції або потоку даних
  • Тут відбуваються ітерація, трансформація та генерація

$$

Щоб клас вважався ітератором, потрібно визначити і __iter__(), і __next__()!

Середній рівень об'єктно-орієнтованого програмування в Python

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

class CoinFlips:
    def __init__(self, number_of_flips):
        self.number_of_flips = number_of_flips  # Зберегти загальну кількість підкидань
        self.counter = 0

    def __iter__(self):
        return self  # Повернути посилання на ітератор

    # Підкинути наступну монету, повернути результат
    def __next__(self):
        if self.counter < self.number_of_flips:
            self.counter += 1
            return random.choice(["H", "T"])
Середній рівень об'єктно-орієнтованого програмування в Python

Використання прикладу ітератора

three_flips = CoinFlips(3)

# Підкиньте монету тричі
next(three_flips)
next(three_flips)
next(three_flips)
H
H
T
Середній рівень об'єктно-орієнтованого програмування в Python

Перебирання ітератора

three_flips = CoinFlips(3)

# Тепер спробуйте пройти всі елементи ітератора
for flip in three_flips:
    print(flip)
T
H
T
None
None
None
...
Середній рівень об'єктно-орієнтованого програмування в Python

StopIteration

...
    def __next__(self):
        # Лише якщо монету ще не підкинули "number_of_flips" разів
        if self.counter < self.number_of_flips:
            self.counter += 1
            return random.choice(["H", "T"])

        else:  # Інакше зупинити виконання через StopIteration
            raise StopIteration
  • Сигналізує про кінець колекції/потоку даних
  • Уникає нескінченних циклів
  • Легко обробляти
Середній рівень об'єктно-орієнтованого програмування в Python

Перебирання ітератора

three_flips = CoinFlips(3)

# Тепер спробуйте пройти всі елементи ітератора
for flip in three_flips:
    print(flip)
H
T
H
Середній рівень об'єктно-орієнтованого програмування в Python

Обробка винятків StopIteration

while True:
    try:
        next(three_flips)  # Взяти наступний елемент three_flips

    # Перехопити виняток StopIteration
    except StopIteration:
        print("Completed all coin flips!")
        break
H
H
H
Completed all coin flips!
Середній рівень об'єктно-орієнтованого програмування в Python

Давайте потренуємось!

Середній рівень об'єктно-орієнтованого програмування в Python

Preparing Video For Download...