← Назад к вопросам

Зачем нужны магические (dunder) методы в генераторе?

1.7 Middle🔥 21 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Роль магических методов в генераторах

Магические методы (dunder methods) — это специальные методы Python, обёрнутые двойными подчёркиваниями, которые делают генераторы полнофункциональными объектами, интегрируя их с синтаксисом и семантикой языка.

iter() — протокол итератора

Генератор должен реализовать протокол итератора, чтобы работать в циклах for:

def countdown(n):
    while n > 0:
        yield n
        n -= 1

gen = countdown(3)
print(iter(gen) is gen)  # True — генератор сам является итератором

# __iter__ возвращает self
for num in gen:
    print(num)  # 3, 2, 1

Без iter() невозможно использовать генератор в цикле или распаковке.

next() — получение следующего значения

__next__() позволяет явно переходить к следующему значению:

gen = countdown(3)
print(next(gen))  # 3 — вызывает __next__()
print(next(gen))  # 2
print(next(gen))  # 1
print(next(gen))  # StopIteration

Это основной механизм для управления потоком выполнения генератора.

enter() и exit() — context manager

Генератор можно использовать как context manager:

def resource_manager():
    print("Acquire resource")
    try:
        yield "resource"
    finally:
        print("Release resource")

with resource_manager() as res:
    print(f"Using {res}")

# Output:
# Acquire resource
# Using resource
# Release resource

del() — очистка ресурсов

Вызывается при удалении генератора из памяти:

import tempfile

def file_reader():
    f = open("data.txt")
    try:
        yield f.read()
    finally:
        f.close()  # Гарантирует закрытие файла

gen = file_reader()
next(gen)
del gen  # Вызывает __del__, закрывает файл

repr() и str() — строковое представление

Определяют, как выглядит генератор в отладке:

def simple_gen():
    yield 1

gen = simple_gen()
print(repr(gen))  # <generator object simple_gen at 0x...>
print(str(gen))   # То же самое

Практический пример: стэк со статусом

class CounterGenerator:
    def __init__(self, limit):
        self.limit = limit
        self.current = 0
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current < self.limit:
            self.current += 1
            return self.current
        raise StopIteration
    
    def __repr__(self):
        return f"CounterGenerator({self.current}/{self.limit})"

cnt = CounterGenerator(3)
print(next(cnt))  # 1
print(repr(cnt))  # CounterGenerator(1/3)

Почему это важно

  • Интеграция с языком — магические методы позволяют генераторам работать с встроенными функциями (iter, next, list, zip)
  • Ресурсное управлениеexit() гарантирует очистку при завершении
  • Отладкаrepr() помогает понять состояние генератора
  • Семантика — делает генераторы полноправными членами экосистемы Python

Магические методы — это не украшение, а фундамент взаимодействия генератора с остальным кодом.