Сообщить об ошибке.

Класс ContextDecorator() модуля contextlib в Python

Использование менеджера контекста в качестве декоратора

Синтаксис:

from contextlib import ContextDecorator

class mycontext(ContextDecorator):
    # код контекстного менеджера

Параметры:

  • нет.

Возвращаемое значение:

  • нет.

Описание:

Базовый класс ContextDecorator() модуля contextlib который позволяет использовать менеджер контекста в качестве декоратора.

Менеджеры контекста, унаследованные от класса contextlib.ContextDecorator(), должны реализовывать методы __enter__ и __exit__ как обычно. Метод __exit__ сохраняет необязательную обработку исключений даже при использовании в качестве декоратора.

Класс contextlib.ContextDecorator используется функцией contextlib.contextmanager(), поэтому вы получаете эту функцию автоматически.

Примеры использования класса ContextDecorator:

from contextlib import ContextDecorator

class mycontext(ContextDecorator):
    def __enter__(self):
        print('Starting')
        return self

    def __exit__(self, *exc):
        print('Finishing')
        return False

>>> @mycontext()
... def function():
...     print('The bit in the middle')
...
>>> function()
# Starting
# The bit in the middle
# Finishing

>>> with mycontext():
...     print('The bit in the middle')
...
# Starting
# The bit in the middle
# Finishing

Это изменение является просто синтаксическим сахаром для любой конструкции следующей формы:

def f():
    with contextmanager():
        # какой то код

Вместо этого класс ContextDecorator позволяет написать:

@contextmanager()
def f():
    # какой то код

Последний пример кода дает понять, что contextmanager относится ко всей функции, а не просто к ее части, а так же уменьшается уровень отступа.

Существующие менеджеры контекста, которые уже имеют базовый класс, могут быть расширены с помощью contextlib.ContextDecorator() в качестве смешанного класса:

from contextlib import ContextBaseClass, ContextDecorator

class mycontext(ContextBaseClass, ContextDecorator):
    def __enter__(self):
        return self

    def __exit__(self, *exc):
        return False

Примечание.
Поскольку декорированная функция должна вызываться несколько раз, базовый менеджер контекста должен поддерживать использование нескольких операторов with. Если это не так, то следует использовать исходную конструкцию с явным оператором with внутри функции.