Python 函数 locals() 被调用改变了

Python the function locals() was changed by just calling it

请阅读这两段代码,我发现唯一不同的是是否打印 locals()。但其中一个是错误的。 请帮助我,谢谢

import numpy as np

class Solution:
    def solve(self, f, a, b, n):
        x = np.linspace(a,b,n)
        # print(locals())
        loc = locals()
        fstr = '''
def fun(x):
    return %s
        ''' % f
        exec(fstr)
        # print(locals())
        fun  = loc['fun']
        y = fun(x)
        print(x,y,sep = '\n')

a = Solution()
a.solve('x+1',-5,5,5)

在这段代码中,我没有打印 locals()

如果我只打印它并在 "fun = loc['fun']" 和 "y = fun(x)" 前面写'#',在 locals()[=14 的输出中有一个名为 'fun' 的键=]

import numpy as np

class Solution:
    def solve(self, f, a, b, n):
        x = np.linspace(a,b,n)
        # print(locals())
        loc = locals()
        fstr = '''
def fun(x):
    return %s
        ''' % f
        exec(fstr)
        print(locals())
        fun  = loc['fun']
        y = fun(x)
        print(x,y,sep = '\n')

a = Solution()
a.solve('x+1',-5,5,5)

但是在这段代码中,我在 locals()

的输出中找不到名为 'fun' 的键
Traceback (most recent call last):
  File "tmp.py", line 20, in <module>
    a.solve('x+1',-5,5,5)
  File "tmp.py", line 15, in solve
    fun  = loc['fun']
KeyError: 'fun'

所有这些似乎都是 "fun = loc['fun']" 和 "y = fun(x)" 决定了 locals()

的输出

但是我觉得python不可能后面的代码能改前面的代码

是的,locals() 就是这样。 locals() 令人困惑且没有很好的记录。

在同一个堆栈帧中重复调用 locals() returns 每次都使用相同的字典,并且每次调用 locals() 更新 该字典与局部(或闭包)变量的当前值。字典作为其 f_locals 属性附加到堆栈帧,访问该属性也会更新字典。

要安全地使用 locals() 而不会意外更改值,您应该复制返回的字典:

current_locals = locals().copy()

否则,即使 运行 您在调试器中的代码也可能会改变其行为,因为调试器通常会访问 f_locals 来检查局部变量。


此外,尝试 exec 代码在局部范围内分配任何变量是官方不支持的,并且行为很奇怪,并且 def 算作一个分配。你不应该为此使用 exec