我可以在不使用 nonlocal 语句的情况下获取非局部变量的值吗?

Can I get the value of a non-local variable without using the nonlocal statement?

我有一个局部变量 x = "local",不幸的是它与一个全局变量和一个非局部变量共享它的名字。在不更改任何名称的情况下,我可以访问所有三个值吗?对于 x = "global"globals(),但是非局部变量呢?

说明问题的最小示例:

x = "global"
def f(x="nonlocal"):
    def g():
        x = "local"
        print(x)  # same as locals()["x"]
        print(globals()["x"])
        # here I want to print the non-local x
    return g

f()()

我不明白你必须使用相同名称的上下文。
无论如何,您可以将外部函数的局部变量捕获为非局部变量。

x = "global"


def f(x="nonlocal"):
    nonlocals = locals()

    def g():
        x = "local"
        print(x)
        print(nonlocals['x'])
        print(globals()["x"])

    return g


f()()

输出:

local
nonlocal
global

编辑: 我没有注意到这个问题在没有使用 nonlocal 的情况下专门提出了这个问题。把它留在这里以防其他人发现它有用。


我质疑这背后的基本原理,但在 Python 3 中,您可以使用 nonlocal 关键字访问先前的范围,在重新声明之前存储它,然后在以后获取它。

x = "global"
def f(x="nonlocal"):
    def g():
        nonlocal x
        y = x
        x = "local"
        print(x)  # same as locals()["x"]
        print(globals()["x"])
        print(y)
    return g


f()()

输出

local
global
nonlocal

虽然您不能用完全按照给定的方式编写代码来执行此操作,但您可以使用 inspect 来获取非局部变量。注意 call 和 return 的变化。如果调用者是外部作用域而不是全局作用域,则前一帧将是 f.

import inspect

x = "global"
def f(x="nonlocal"):
    def g():
        x = "local"
        print(x)
        print(globals()["x"])
        print(inspect.currentframe().f_back.f_locals["x"])

    return g()


f()

输出

local
global
nonlocal

在这种特定情况下,这可能无济于事,这实际上取决于您对 f 的内容的控制程度。如果你无法控制它,你也可以使用 monkey-patch f。很大程度上取决于上下文。