首页 > 解决方案 > Python 函数 locals() 只是通过调用它来改变

问题描述

请阅读这两个代码,我发现唯一不同的是是否打印 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() 的输出中有一个名为 '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不可能后面的代码可以改变前面的代码

标签: pythonfunctionlocal-variables

解决方案


是的,这发生在locals(). locals()令人困惑并且没有很好的记录。

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

为了locals()安全地使用值而不发生不可预测的变化,您应该复制返回的字典:

current_locals = locals().copy()

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


此外,官方不支持尝试exec在本地范围内分配任何变量的代码,并且行为怪异,并被def视为分配。exec无论如何,你不应该使用它。


推荐阅读