Можно ли сделать контекстно-зависимый менеджер контекста Python, который сохраняет, изменяет и восстанавливает состояние?

У меня есть пара функций Python, которые в настоящее время переворачивают глобальную переменную между двумя значениями. Я хотел бы превратить их в менеджеры контекста, чтобы я мог использовать их как with блоков, устанавливая переменную внутри блока, но восстанавливая ее после. Вот желаемое поведение:

>>> MODE
'user'
>>> mode_sudo()  # Sets MODE to 'sudo'...
>>> MODE
'sudo'
>>> mode_user()  # Sets MODE to 'user'...
>>> MODE
'user'
>>> with mode_sudo():
...    print MODE
'sudo'
>>> MODE
'user'

Возможна ли такая химера?

ОБНОВЛЕНИЕ: просто для ясности, вот реализация только для менеджера контекста:

from contextlib import contextmanager

@contextmanager
def mode_sudo():
    global MODE
    old_mode = MODE
    MODE = 'sudo'
    yield
    MODE = old_mode

@contextmanager
def mode_user():
    global MODE
    old_mode = MODE
    MODE = 'user'
    yield
    MODE = old_mode

Вызов их без ключевого слова возвращает генератор. Есть ли способ получить поведение переключения режима с помощью вызова функции plain-vanilla и менеджера шоколадного контекста?

2 ответа

Решение

Сделай это так:

class mod_user:

    def __init__(self):
        global MODE
        self._old_mode = MODE
        MODE = "user"

    def __enter__(self):
        pass

    def __exit__(self, *args, **kws):
        global MODE
        MODE = self._old_mode

MODE = "sudo"

with mod_user():
    print MODE  # print : user.

print MODE  # print: sudo.

mod_user()
print MODE   # print: user.

Простой способ:

from contextlib import contextmanager
@contextmanager
def mode_user():
    global MODE
    old_mode = MODE
    MODE = "user"
    yield
    MODE = old_mode

то же самое для mode_sudo(), Смотрите документ для более подробной информации. Это на самом деле ярлык для всего "определить класс, который реализует __enter__ а также __exit__"-вещь.

Другие вопросы по тегам