Python 中 Local 命名空间的内容

Content of the Local namespace in Python

提问人:gambarimas87 提问时间:6/25/2023 最后编辑:gambarimas87 更新时间:6/25/2023 访问量:57

问:

我在 Python 文档的这一页中读到,函数的本地命名空间是在调用函数时创建的。

在下面的示例代码中,我使用 function 来获取 function 的本地命名空间(字典)。令我惊讶的是,这个函数返回的字典包括 identifier ,只有在我调用函数后才会出现在函数的主体中。locals()g()f_varg()locals()

# local_namespace_test.py
def f():

    f_var = 55

    def g():
        g_var = 3
        print(f"locals in g(): {locals()}")
        print(f_var)
        return

    g()
    return

f()

为什么函数的本地命名空间在这种情况下包含该名称?
为什么如果我删除该行,那么不在字典中返回 ?
g()f_varprint(f_var)f_varlocals()

运行上述代码的输出:

$ python3 local_namespace_test.py 
locals in g(): {'g_var': 3, 'f_var': 55}
55

运行上述代码的输出,并注释了行:print(f_var)

$ python3 local_namespace_test.py 
locals in g(): {'g_var': 3}
Python 命名空间

评论

1赞 quamrana 6/25/2023
我发现 mCoding 的这个视频对理解变量范围非常有帮助。
2赞 Tim Roberts 6/25/2023
这与 Python 有点不寻常的范围规则有关。Python 需要预扫描您的函数,以确定您使用的变量是全局变量、局部变量还是非局部变量。它会记住这一点,因此可以监视“设置前使用”错误。

答:

0赞 destructioneer 6/25/2023 #1

Python 将从内到外寻找变量。在这种情况下,您有一个“链式”调用堆栈。global -> f() -> g()

因此,引用了两个变量:和 . 也定义在 so 中,因此是一个局部变量,因此在 的内部命名空间中。g()g_varf_varg_varg()g_varg()

f_var在语句中引用,但未在此处定义。因此,如果不同的命名空间包含对“堆栈”的引用并上升到“堆栈”,则 Python 将进行查找。该函数包含 和 的定义,因此将 中的命名空间条目复制到 。g()printf_varf()f_varf_varf()g()

如果没有对 in 的引用(即省略 print 语句),则不会被复制到内部命名空间,因为 中不需要它。f_varg()f_varg()

如果函数不包含 的定义,Python 将“进一步向上”查看,即在全局命名空间中,如果已定义。所以在这种情况下:f()f_varf_var

f_var=44
def f():
    def g():
        g_var = 3
        print(f"locals in g(): {locals()}")
        print(f"globals in g(): {globals()}")
        print(f_var)
        return
    g()
    return
f()

将返回

locals in g(): {'g_var': 3}
globals in g(): {'__name__': '__main__', [...] 'f_var': 44, 'f': <function f at 0x7f9286480e18>}
44

返回值将是 global ,它不在本地命名空间中,而是在全局命名空间中。f_var

评论

0赞 gambarimas87 6/25/2023
理解。但是,您的回答让我认为 Python 甚至在首次执行函数体之前就会设置函数的本地命名空间。根据您的回答,似乎 Python 会在执行之前仔细阅读函数体,如果有一些只能在封闭范围内找到的引用,它将从该封闭范围复制到函数的本地范围。我没有在我读过的关于 Python 范围的任何地方找到这种行为。你能给我一些参考资料来在线阅读吗?