如何暂时分配成员变量?

Max*_*axB 12 python python-2.7 python-decorators python-descriptors

我经常发现我需要临时分配一些成员变量,例如

old_x = c.x
old_y = c.y
# keep c.z unchanged

c.x = new_x
c.y = new_y

do_something(c)

c.x = old_x
c.y = old_y
Run Code Online (Sandbox Code Playgroud)

但我希望我能简单地写一下

with c.x = new_x; c.y = new_y:
    do_something(c)
Run Code Online (Sandbox Code Playgroud)

甚至

do_something(c with x = new_x; y = new_y)
Run Code Online (Sandbox Code Playgroud)

Python的装饰器或其他语言功能能够实现这种模式吗?(我可以c根据需要修改课程)

Łuk*_*ski 20

可以轻松地使用上下文管理器.

引用官方文档:

上下文管理器的典型用途包括保存和恢复各种全局状态,锁定和解锁资源,关闭打开的文件等.

似乎保存和恢复状态正是我们想要在这里做的.

例:

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
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的答案,但您可能希望将上下文管理器的内部包装在`try/finally`中 (7认同)

Mos*_*oye 5

我认为contextmanager应该做你想做的事:

from contextlib import contextmanager

@contextmanager
def current_instance(c, temp_x, temp_y):
    old_x, old_y = c.x, c.y
    c.x, c.y = temp_x, temp_y
    yield c
    c.x, c.y = old_x, old_y

with current_instance(c, x, y) as c_temp:
    do_something(c_temp) 
Run Code Online (Sandbox Code Playgroud)