用于包含范围的Python locals()

mmt*_*het 8 python environment scope locals python-3.x

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

大家好.

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

考虑:

def a():
    x = 1
    def b():
        print(locals())
        print(globals())
    b()
Run Code Online (Sandbox Code Playgroud)

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

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

def a():
    x = 1
    def b():
        a = x+2
        x = 3
    b()
Run Code Online (Sandbox Code Playgroud)

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

Ser*_*lis 6

代码中发生的事情是,当python看到方法中的x=3行时b(),它会xb函数中使用范围重新创建,而不是在函数中使用xwith the scope a.

因为你的代码然后:

    a = x+2
    x = 3
Run Code Online (Sandbox Code Playgroud)

它是说你需要x在引用它之前定义内部作用域.

但是,当你没有xb函数内部进行赋值时,python不会尝试使用较低的作用域x,也不会抛出任何错误.

以下代码将说明这一点:

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

    def c():
        print (x)

    b()
    c()
    print (x)

a()
Run Code Online (Sandbox Code Playgroud)

但是,如果您要声明x,global可以在函数中使用它,如下所示:

def a():
    global x
    x = 1

    def d():
        global x
        x += 2

    print (x)
    d()
    print (x)

a()
Run Code Online (Sandbox Code Playgroud)

Python 3还添加了一个nonlocal关键字,允许您从封闭范围访问变量,用法如下:

def a():
    x = 1

    def d():
        nonlocal x
        x += 2

    print (x)
    d()
    print (x)

a()
Run Code Online (Sandbox Code Playgroud)

将打印与global示例相同的结果.


如果我错过了阅读问题:

根据在Python中调用命名空间获取本地人的答案:

您可以使用:

import inspect

def a():
    x = 1

    def d():
        frame = inspect.currentframe()
        try:
            print (frame.f_back.f_locals)
        finally:
            del frame
    d()

a()
Run Code Online (Sandbox Code Playgroud)

获取函数调用者的本地范围.


kir*_*off 1

该语句print(locals())引用最近的封闭范围,即函数def b():。调用时b(),您将打印此 b 函数的局部变量,并且 x 的定义超出了范围。

def a():
    x = 1
    def b():
        print(locals())
        print(globals())
    b()
    print(locals())
Run Code Online (Sandbox Code Playgroud)

会将 x 打印为局部变量。

对于你的第二个问题:

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

>>> a()
Run Code Online (Sandbox Code Playgroud)

没有给出错误。

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

>>> a()
Run Code Online (Sandbox Code Playgroud)

没有给出错误。

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

>>> a()
Run Code Online (Sandbox Code Playgroud)

给出以下错误:UnboundLocalError: local variable 'x' referenced before assignment

IMO(请检查),在第三种情况下,主体中的第一个语句在最封闭的范围中b()查找 x 的值。在此范围内,x 被分配在下一行。如果您只有语句,则 x 在大多数封闭范围中找不到,并且在“下一个”封闭范围中找到,其中.a = x+2x = 1