За что отвечают магические методы __new__, __init__, __enter__ и __exit__? Как реализовать собственный контекстный менеджер через класс или через генератор с декоратором @contextmanager?

__new__ создаёт экземпляр, __init__ инициализирует его, а __enter__/__exit__ управляют входом и выходом из with. Контекстный менеджер нужен для гарантированного освобождения ресурса.

Короткий ответ

Что ответить на собеседовании

new создаёт экземпляр, init инициализирует его, а enter/exit управляют входом и выходом из with. Контекстный менеджер нужен для гарантированного освобождения ресурса.

Подробный разбор

Ответ с пояснениями

new создаёт экземпляр, init инициализирует его, а enter/exit управляют входом и выходом из with. Контекстный менеджер нужен для гарантированного освобождения ресурса.

Классовый вариант:

class ManagedFile:
    def __init__(self, path):
        self.path = path
    def __enter__(self):
        self.file = open(self.path, encoding='utf-8')
        return self.file
    def __exit__(self, exc_type, exc, tb):
        self.file.close()
        return False

Эквивалентный генератор:

from contextlib import contextmanager

@contextmanager
def managed_file(path):
    file = open(path, encoding='utf-8')
    try:
        yield file
    finally:
        file.close()

__init__ не возвращает экземпляр; его результат должен быть None. Истинное значение из __exit__ подавляет исключение тела, поэтому возвращать его без необходимости нельзя. Если вход не удался, cleanup частично созданного ресурса организуют отдельно.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее