Можно ли создать контекстно-зависимый менеджер контекста Python, который сохраняет, изменяет и восстанавливает состояние? - PullRequest
3 голосов
/ 09 августа 2011

У меня есть пара функций 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 ]

5 голосов
/ 09 августа 2011

Сделай так:

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.
2 голосов
/ 09 августа 2011

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

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

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

...