【问题标题】:When is the locals dictionary set?locals 字典什么时候设置?
【发布时间】:2017-09-07 12:06:04
【问题描述】:

一个模块拥有一个字典来跟踪它的上下文,例如在某个执行点定义的名称。如果导入了module,则可以通过vars(module)(或module.__dict__)或通过调用模块本身中的locals 内置函数来访问此字典:

更新并返回一个表示当前本地符号表的字典。

但当我尝试从函数访问本地字典时,我发现自己有点困惑。仅包含以下内容的脚本的输出是一个空字典:

def list_locals():
    print(locals())

list_locals()

但另一方面,如果脚本仅包含以下内容,则输出是预期的字典,包含 __name____doc__ 和其他模块级变量:

print(locals())

那么,locals 字典的内容是什么时候设置的呢? 另外,locals函数定义中的“更新”是什么意思?

【问题讨论】:

  • 在模块级别尝试print(locals() is globals())
  • @Chris_Rands 是的,这是我困惑的一部分。

标签: python namespaces symbol-table


【解决方案1】:

模块的命名空间是 global 命名空间,通过globals() 访问。没有单独的局部命名空间,所以locals(),在函数之外,只返回全局命名空间。

只有函数有本地命名空间。请注意,locals() 是该命名空间的单向反映;函数的 CPython 实现经过高度优化,您无法通过 locals() 字典添加或更改局部变量。只要命名空间在调用该函数之间发生变化,locals() 返回的字典就会更新。

还要注意,像 list / dict / set 理解、生成器表达式和类体之类的东西实际上也作为函数执行,尽管具有不同的命名空间规则。在这种情况下,locals() 也将返回单独的函数本地命名空间。

【讨论】:

    【解决方案2】:

    如果您在同一个函数调用期间多次调用locals(),它将返回同一个字典。

    >>> def f():
    ...     d = locals()
    ...     assert 'd' not in d
    ...     locals()
    ...     assert 'd' in d
    ...     assert d is locals()
    ...     print(d)
    ... 
    >>> f()
    {'d': {...}}
    

    在这种情况下,“更新”意味着更新此字典的内容以反映存在的局部变量的当前范围,但如果您保留对该字典的引用,则仍将使用该字典。

    还要注意,locals 字典不包含'f' 的键,即使您可以在函数执行过程中访问它。如果不明显,那是全局的,而不是本地的。

    【讨论】:

    • 感谢您对“更新”含义的解释。尽管我显然混淆了localsglobals,但我想说文档对这种行为有些回避。再次感谢您的澄清。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    • 2011-05-15
    • 2010-11-27
    • 2020-03-15
    • 1970-01-01
    相关资源
    最近更新 更多