new создаёт экземпляр, init инициализирует его, а enter/exit управляют входом и выходом из with. Контекстный менеджер нужен для гарантированного освобождения ресурса.
За что отвечают магические методы __new__, __init__, __enter__ и __exit__? Как реализовать собственный контекстный менеджер через класс или через генератор с декоратором @contextmanager?
__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 частично созданного ресурса организуют отдельно.