Python 上下文管理器恢复变量的值?

Python Context Manager to restore a variable's value?

您将如何编写上下文管理器来将变量恢复为其原始值?例如:

x = 5
with Restorer(x):
   x = 6
   ...
print(x)

输出将是: 5

这只有在特定情况下才有可能。通常上下文管理器只获取x的值(实际上是引用)。它无法访问变量本身。

对于全局变量,如果调用函数定义在同一个模块中(或者代码只是放在同一个模块中,没有周围的函数),调用可以写成

with Restorer('x'):

那么恢复器可以是这样的(省略错误检查):

class Restorer:

    def __init__(self, varName):
        self.varName = varName

    def __enter__(self):
        self.oldValue = globals()[self.varName]

    def __exit__(self, exc_type, exc_val, exc_tb):
        globals()[self.varName] = self.oldValue

利用 contextlib.contextmanager,您可以在 yield 语句后将 x 重新分配为其原始值:

import contextlib

x = 5
@contextlib.contextmanager
def Restorer(val):
  yield 
  global x
  x = val

print(x)
with Restorer(x):
  x = 6
  print('in contextmanager:', x)

print('outside contextmanager', x)

输出:

5
in contextmanager: 6
outside contextmanager 5

您可以滥用 class 语句来引入临时 "scope":

x = 5
class Foo:
    print(x)
    x = 6
    print(x)
print(x)

这个 "works" 因为 Foo 没有建立一个真正的新范围,这意味着第一个 print(x) 指的是当前范围内的名称 x,但是在临时无人区分配以准备创建同名的 class 属性,该属性用于正文的其余部分。但是,我相信这足以模拟您的要求。

(也就是说,实际上不要在实践中使用它。如果您需要某种临时覆盖,请编写适当的函数或手动保存值。)

这更多地与名称的范围有关,而不是与变量有关。

您可以通过创建具有块行为的函数来创建作用域:

def behaviour():
    x = 6
    ...

x = 5
behaviour()
print(x)

输出:

5

或者,您可以引入一个新名称:

x = 5
y = 6
...
print(x)

输出:

5