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

87
11

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


>>> 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


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

спросил(а) 2021-01-27T23:37:13+03:00 2 месяца, 2 недели назад
1
Решение
106

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

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.

ответил(а) 2021-01-27T23:37:13+03:00 2 месяца, 2 недели назад
76

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


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

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

ответил(а) 2021-01-27T23:37:13+03:00 2 месяца, 2 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема