Как временно назначить переменные-члены?

Я часто обнаруживаю, что мне нужно временно назначить некоторые переменные-члены, например

old_x = cx old_y = cy # keep cz unchanged cx = new_x cy = new_y do_something(c) cx = old_x cy = old_y 

но я бы хотел просто написать

 with cx = new_x; cy = new_y: do_something(c) 

или даже

 do_something(c with x = new_x; y = new_y) 

Могут ли декораторы Python или другие языковые функции включить такой шаблон? (Я мог бы изменить класс c по мере необходимости)

    5 Solutions collect form web for “Как временно назначить переменные-члены?”

    Контекстные менеджеры могут быть легко использованы для этого.

    Цитирование официальных документов:

    Типичное использование контекстных менеджеров включает в себя сохранение и восстановление различных видов глобального состояния, блокировку и разблокирование ресурсов, закрытие открытых файлов и т. Д.

    Кажется, что сохранение и восстановление состояния – это именно то, что мы хотим сделать здесь.

    Пример:

     from contextlib import contextmanager @contextmanager def temporary_change_attributes(something, **kwargs): previous_values = {k: getattr(something, k) for k in kwargs} for k, v in kwargs.items(): setattr(something, k, v) try: yield finally: for k, v in previous_values.items(): setattr(something, k, v) class Something(object): def __init__(self, x, y): self.x = x self.y = y def say_hello(self): print("hello", self.x, self.y) s = Something(1, 2) s.say_hello() # hello 1 2 with temporary_change_attributes(s, x=4, y=5): s.say_hello() # hello 4 5 s.say_hello() # hello 1 2 

    Я думаю, что contextmanager должен делать то, что вы хотите:

     from contextlib import contextmanager @contextmanager def current_instance(c, temp_x, temp_y): old_x, old_y = cx, cy cx, cy = temp_x, temp_y yield c cx, cy = old_x, old_y with current_instance(c, x, y) as c_temp: do_something(c_temp) 

    Вы также можете сделать это изначально, используя __enter__ и __exit__ . Упрощенный пример:

     class SomeObject(object): def __init__(self): self.a = 1 self.b = 2 self.c = 3 class Temporary(object): def __init__(self, target, **kv): self.target = target self.to_set = kv self.to_restore = {} def __enter__(self): self.to_restore = map(partial(getattr, self.target), filter(partial(hasattr, self.target), self.to_set.keys())) for k,v in self.to_set.items(): if hasattr(self.target, k): self.to_restore[k] = getattr(self.target, k) setattr(self.target, k, v) def __exit__(self, *_): for k,v in self.to_restore.items(): setattr(self.target, k, v) for k in self.to_set.keys(): if k not in self.to_restore: delattr(self.target, k) o = SomeObject() print(o.__dict__) with Temporary(o, a=42, d=1337): print(o.__dict__) print(o.__dict__) 

    mock предоставляет эту функциональность, особенно посмотрите на использование контекстного менеджера patch.object . Он находится в основных библиотеках в python3 и доступен на pypi для более старого python.

    Настроить:

     >>> class C: ... def __init__(self, x, y, z): ... self.x = x ... self.y = y ... self.z = z ... >>> c = C(0,1,2) 

    Демонстрация использования:

     >>> print(cx, cy, cz) 0 1 2 >>> with patch.object(c, 'x', 'spam'), patch.object(c, 'y', 'eggs'): ... print(cx, cy, cz) ... spam eggs 2 >>> print(cx, cy, cz) 0 1 2 

    Решение Goofy

     >>> class Foo(object): def __init__(self): self._x = [] self._y = [] @property def x(self): return self._x[-1] or None @x.setter def x(self, val): self._x.append(val) def reset_vals(self): if len(self._x) > 1: self._x.pop() >>> bar = Foo() >>> bar.x = 1 >>> bar.x 1 >>> bar.x = 2 >>> bar.x 2 >>> bar.reset_vals() >>> bar.x 1 >>> bar.reset_vals() >>> bar.x 1 

    Все еще тупой, но менее

     >>> class Foo(object): def __init__(self): pass >>> import copy >>> bar = Foo() >>> bar.x = 1 >>> bar.x 1 >>> bar2 = copy.copy(bar) >>> bar2.x 1 >>> bar2.x = 5 >>> bar2.x 5 >>> bar <__main__.Foo object at 0x0426A870> >>> bar.x 1 
     
    Interesting Posts for Van-Lav

    как разбить столбец кортежей в pandas dataframe?

    Sklearn Randomized Logistic Regression дает ошибку «ValueError: количество классов должно быть больше одного»

    Как использовать расширенные уровни активации в Keras?

    Распечатайте символы «\ n» или новые символы как часть вывода на терминале

    Как расширить класс в python?

    Маршрутизация домена в колбе

    Как повторить фрагмент кода определенное количество раз в python

    как я могу контролировать производительность окон обслуживания из других окон службы с помощью библиотеки win32service и командной строки cmd в python

    Джанго с осколком и фантомами болезненно медленно

    Может ли класс cdef хранить переменную, которая не объявлена ​​(type-)?

    Python: учитывая текущее время в UTC, как вы определяете время начала и окончания дня в определенном часовом поясе?

    lxml xml разбор с тегами html внутри тегов xml

    GAE Appstats RPC График временной шкалы показывает длительные задержки со сложными запросами NDB

    Может ли скрипт python выполнять функцию внутри сценария bash?

    Запуск тестов Django в PyCharm

    Python - лучший язык программирования в мире.