Менеджеры контекста
Часть раздела Объектно-ориентированное программирование путешествия по Python на Coddy. Урок 41 из 64.
Менеджеры контекста позволяют выделять и освобождать ресурсы именно тогда, когда это необходимо. Они обеспечивают надлежащую очистку, даже если возникают ошибки.
Вот самый распространённый пример использования инструкции with:
with open('example.txt', 'w') as file:
file.write('Hello, world!')
# Здесь файл автоматически закрываетсяФайл автоматически закрывается после блока, даже если возникает исключение.
Создай собственный менеджер контекста, реализовав методы __enter__ и __exit__:
class MyContext:
def __enter__(self):
print("Entering the context")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Exiting the context")
return False # Не подавлять исключенияИспользуй свой собственный менеджер контекста:
with MyContext() as ctx:
print("Inside the context")Вывод:
Entering the context
Inside the context
Exiting the contextСоздай более практичный менеджер контекста для подключений к базе данных:
class DatabaseConnection:
def __init__(self, db_name):
self.db_name = db_name
self.connection = None
def __enter__(self):
print(f"Connecting to {self.db_name}")
self.connection = f"Connection to {self.db_name}"
return self.connection
def __exit__(self, exc_type, exc_val, exc_tb):
print(f"Closing connection to {self.db_name}")
self.connection = None
with DatabaseConnection("users_db") as conn:
print(f"Using {conn}")
print("Performing database operations...")Обрабатывайте исключения в менеджерах контекста:
class SafeContext:
def __enter__(self):
print("Setting up resources")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Cleaning up resources")
if exc_type:
print(f"An exception occurred: {exc_val}")
return False # Не подавляйте исключение
with SafeContext():
print("Working with resources")
# raise ValueError("Something went wrong") # Раскомментируйте для проверкиВывод:
Connecting to users_db
Using Connection to users_db
Performing database operations...
Closing connection to users_db
Setting up resources
Working with resources
Cleaning up resourcesМетод __exit__ получает три параметра:
exc_type: тип исключения (или None)exc_val: значение исключения (или None)exc_tb: трассировка исключения (или None)
Ключевой момент: менеджеры контекста используют методы __enter__ и __exit__ для управления ресурсами. Инструкция with автоматически вызывает эти методы, обеспечивая правильную подготовку и очистку. Это особенно полезно для файлов, подключений к базам данных и других ресурсов, для которых необходимо гарантировать очистку.
Задание
ЛегкоВ этом задании ты реализуешь класс менеджера контекста, который измеряет время, прошедшее между входом в блок контекста и выходом из него.
timer.py— содержит реализацию классаTimer(этот файл нужно редактировать)driver.py— содержит полный набор тестов (не изменяй его)
Реализуй менеджер контекста Timer в timer.py, следуя комментариям TODO. Класс должен:
- Записывать время начала при входе в контекст
- Записывать время окончания при выходе
- Вычислять и выводить прошедшее время
Попробуйте сами
from timer import Timer
import time
# Обработка тестового случая
test_case = input()
if test_case == "basic_test":
# Проверка базовой функциональности
with Timer():
# Имитируем выполнение некоторой работы
time.sleep(2) # Это заставляет программу ждать 2 секунды
elif test_case == "nested_contexts":
# Проверка вложенных менеджеров контекста
with Timer():
time.sleep(1)
with Timer():
time.sleep(1)
elif test_case == "exception_handling":
# Проверка обработки исключений внутри контекста
try:
with Timer():
time.sleep(1)
raise ValueError("Test exception")
except ValueError as e:
print(f"Caught exception: {e}")
elif test_case == "zero_sleep":
# Проверка с минимальной задержкой
with Timer():
time.sleep(0.001)
elif test_case == "multiple_timers":
# Проверка нескольких таймеров последовательно
with Timer():
time.sleep(1)
with Timer():
time.sleep(0.5)
with Timer():
time.sleep(2)
elif test_case == "as_decorator":
# Проверка таймера в контексте функции
def timed_function():
with Timer():
time.sleep(2)
timed_function()
else:
# Тест по умолчанию — проверка базовой функциональности
with Timer():
# Имитируем выполнение некоторой работы
time.sleep(2) # Это заставляет программу ждать 2 секунды
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Введение в ООПВнешние файлыКлассы и объектыПараметр selfМетодыАтрибутыМетод-конструктор (__init__)Повторение — простой калькулятор4Наследование
Основы наследованияФункция super()Переопределение методовМножественное наследованиеПорядок разрешения методовПовторение: иерархия сотрудников7Специальные методы
Введение в магические методыПерегрузка операторовМагические методы контейнеровПовторение — пользовательский список10Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн «Одиночка»Паттерн «Фабрика»Паттерн «Наблюдатель»Паттерн «Стратегия»2Декораторы
Введение в декораторыДекоратор свойстваДекоратор статического методаДекоратор метода класса5Полиморфизм
Переопределение методов: повторениеУтиная типизацияАбстрактные классы и методыПроектирование интерфейсовПовторение — калькулятор фигур8Продвинутые концепции ООП
Композиция и наследованиеМиксиныСтатические методы и методы классаДекораторы классовМенеджеры контекста11Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»3Свойства классов
Переменные экземпляра и классаДекораторы свойствПриватные атрибутыПовторение — менеджер банковского счёта6Инкапсуляция
Публичные, защищённые и приватные членыМодификаторы доступаСокрытие информацииПродвинутые декораторы свойствПовторение — система учёта студентов12Проект: Система управления библиотекой
Обзор проектаКлассы книг и пользователейСистема выдачи книгФункция поискаИнтерфейс администратораТестирование и интеграцияПотренируйтесь самостоятельно: Онлайн-компилятор Python