写入 locals() 的工作方式与说明它不是的文档相反

Writing to locals() works in contrast to documentation saying its not

我目前正在研究变量范围以及如何修改/复制它们,因为我想在 IPython 中动态地后处理一些结果。 关于 locals()、vars() 和 globals() 的困惑现在对我来说是真实存在的。 特别是因为这段代码的输出:

Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> locals()["test"] = 5
>>> print(test)
5

根据不仅仅是简短的文档,这在我看来是不可能的:

Note, the locals dictionary is only useful for reads since updates to the locals dictionary are ignored.

(出于 vars() 函数的 description 中所述的任何原因)

希望有人能赐教:)

你在哪里阅读这篇文章?两者 Py 2 docs and Py 3 docs 都有以下免责声明:

Note: The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.

这准确地说明了这是什么:实现细节。当然,它适用于 CPython,但它可能不适用于其他各种解释器,如 IronPython 和 Jython。这就是所谓的 hack。

不要依赖它来更新任何变量。甚至不要尝试做任何严重的事情,因为它会导致未定义的行为。

在 CPython 3.6.0 中,help(locals) 有以下注释:

NOTE: Whether or not updates to this dictionary will affect name lookups in
the local scope and vice-versa is *implementation dependent* and not
covered by any backwards compatibility guarantees.

然而,CPython 2.7.13 没有这样的注释。

在模块范围内,locals() returns 可以修改的全局模块字典。函数中的局部变量是不同的。这里,变量没有改变。正如其他地方提到的,这完全取决于实现。你不能指望 locals() 作为一名作家。

>>> def foo():
...     x = 2
...     locals()['x'] = 3
...     print(x)
... 
>>> 
>>> foo()
2

编辑

cpython中,局部变量变成了框架对象上的槽。当 python 运行程序时,"x" 不再是 "x",它是槽中的索引。

>>> from dis import dis
>>> dis(foo)
  2           0 LOAD_CONST               1 (2)
              2 STORE_FAST               0 (x)

  3           4 LOAD_CONST               2 (3)
              6 LOAD_GLOBAL              0 (locals)
              8 CALL_FUNCTION            0
             10 LOAD_CONST               3 ('x')
             12 STORE_SUBSCR

  4          14 LOAD_GLOBAL              1 (print)
             16 LOAD_FAST                0 (x)
             18 CALL_FUNCTION            1
             20 POP_TOP
             22 LOAD_CONST               0 (None)
             24 RETURN_VALUE

STORE_FAST 0表示将当前值(刚好是2)存入slot 0.