用于包含范围的Python locals()

时间:2013-02-25 22:21:41

标签: python python-3.x scope environment locals

TL; DR:我想要一个在包含范围内查找的locals()。

大家好。

我正在向一些化学家朋友讲授关于Python编程的课程,我想确保我真正了解范围。

考虑:

def a():
    x = 1
    def b():
        print(locals())
        print(globals())
    b()

Locals打印一个空的环境,globals打印通常的全局变量。如何访问存储x的环境?显然,口译员知道它,因为我可以参考它。

相关:什么时候发生范围?仅当包含x = 3时,a = x + 2上的以下nameErrors:

def a():
    x = 1
    def b():
        a = x+2
        x = 3
    b()

如果您注释掉x = 3,则代码可以正常工作。这是否意味着python在解释代码之前会对代码进行词法范围传递?

1 个答案:

答案 0 :(得分:0)

python3 -c "help(locals)"谈到locals函数:

locals()
    Return a dictionary containing the current scope's local variables.

这意味着在locals()中调用b()只会向您显示b()局部变量。这并不意味着b()在其范围之外看不到变量,而是locals()仅返回b()本地变量的信息。

您可能想要使b()显示有关调用函数变量的信息。为此,请使用以下代码(其中显示了b()的局部变量):

def a():
    x = 1
    def b():
        print(locals())
    b()

并将其替换为该代码(使用inspect模块来获取调用帧的本地信息)

def a():    
    x = 1
    def b():
        import inspect
        print(inspect.currentframe().f_back.f_locals)
    b()

关于您的其他问题:

def a():
    x = 1
    def b():
        a = x+2
        x = 3
    b()

您得到的错误是因为Python 3允许您设置/分配全局变量和外部作用域局部变量,前提是您使用globalnonlocal关键字对其进行了声明。 (我不会在这里解释它们;我只是说您自己查找它们不会有任何问题。)

如果删除x = 3行(保留a = x+2行),则代码将运行,因为正在使用x的值,但未设置。相反,如果删除a = x+2行(保留x = 3行),则代码将运行,因为它将在x范围内创建一个新的b()

如果同时保留这两行,Python将不知道x是否应该引用当前范围之外的x(正如a = x+2所暗示的那样)或是否应该引用x范围内的b()(如x = 3所建议的那样。)

如果您希望xb()本地,那么您不应该在那儿拥有a = x+2行,至少在将x设置为{{ 1}}。但是,如果您希望x = 3x的{​​{1}},则应该将a()声明为xx,如下所示:< / p>

nonlocal

如果您感到困惑,请记住,Python将允许您使用全局变量和在当前作用域之外创建的变量,但前提是您不分配他们。 (读取全局变量通常是可以接受的,但是设置它们并不受欢迎。)

如果要设置全局变量或非局部变量,则必须使用b()(对于全局变量)或def a(): x = 1 def b(): nonlocal x # use a()'s x a = x+2 x = 3 b() (对于非局部变量)声明这些变量,如上面的代码所示。

我希望这会有所帮助。