Python 从函数内部更新局部变量

Python 从函数内部更新局部变量,python,Python,我想写一个函数,它接收本地名称空间字典并更新它。大概是这样的: def UpdateLocals(local_dict): d = {'a':10, 'b':20, 'c':30} local_dict.update(d) a = 1 UpdateLocals(locals()) # prints 20 print a 当我从交互式python shell调用此函数时,它可以正常工作,如下所示: def UpdateLocals(local_dict): d = {'a':10

我想写一个函数,它接收本地名称空间字典并更新它。大概是这样的:

def UpdateLocals(local_dict):
  d = {'a':10, 'b':20, 'c':30}
  local_dict.update(d)
a = 1
UpdateLocals(locals())

# prints 20
print a
当我从交互式python shell调用此函数时,它可以正常工作,如下所示:

def UpdateLocals(local_dict):
  d = {'a':10, 'b':20, 'c':30}
  local_dict.update(d)
a = 1
UpdateLocals(locals())

# prints 20
print a
但是,当我从函数内部调用
UpdateLocals
时,它并没有达到我预期的效果:

def TestUpdateLocals():
  a = 1
  UpdateLocals(locals())
  print a

# prints 1
TestUpdateLocals()
我怎样才能使第二个案例像第一个一样有效

更新:

阿斯温的解释很有道理,对我很有帮助。但是,我仍然需要一种机制来更新局部变量。在我想出一个不那么丑陋的方法之前,我将做以下几点:

def LoadDictionary():
  return {'a': 10, 'b': 20, 'c': 30}

def TestUpdateLocals():
  a = 1
  for name, value in LoadDictionary().iteritems():
    exec('%s = value' % name)

当然,string语句的构造可以自动化,细节可以对用户隐藏。

局部变量在这里不更新,因为在第一种情况下,声明的变量具有全局范围。但是,当在函数内部声明时,变量将失去其外部的作用域

因此,
UpdateLocals
函数中的locals()的原始值不会更改

PS:这可能与您的问题无关,但在Python中使用camel case并不是一个好的实践。尝试使用另一种方法

update\u locals()
而不是
UpdateLocals()

编辑回答评论中的问题:

有一种称为系统堆栈的东西。在代码执行期间,此系统堆栈的主要任务是管理局部变量,确保在完成被调用函数的执行后,控制返回到正确的语句,等等

因此,每次进行函数调用时,都会在堆栈中创建一个新条目, 它包含在return语句之后控件必须返回的行号(或指令号)和一组新的局部变量


当控件位于函数内部时,局部变量将从堆栈项中获取。因此,两个函数中的局部变量集并不相同。当控件退出函数时,堆栈中的条目弹出。因此,您在函数中所做的更改将被删除,除非这些变量具有全局范围。

您提出了一个非常好的问题。事实上,更新局部变量的能力在为机器学习或游戏保存和加载数据集时非常重要。然而,大多数Python语言的开发人员还没有意识到它的重要性。他们过于注重整合和优化,而整合和优化同样重要

想象你正在开发一个游戏或运行一个深度神经网络(DNN),如果所有的局部变量都是可序列化的,那么保存整个游戏或DNN可以简单地放在一行中作为
print(locals())
,加载整个游戏或DNN可以简单地放在一行中作为
locals().update(eval(sys.stdin.read())

目前,
globals()

默认局部变量的作用如以下函数locals()所述: 不应删除对默认本地词典的修改 尝试。如果需要查看,请传递一个显式本地词典 函数exec()返回后代码对局部变量的影响

他们之所以以这种方式设计Python,是因为优化并将
exec
语句整合到函数中:

如果没有函数,则无法动态修改函数的局部变量 几个后果:通常情况下,函数局部变量不存储在 字典,但数组,其索引在编译时确定 来自已知的地区。这至少与新加入的本地人有冲突 行政长官。旧的exec声明回避了这一点,因为 编译器知道,如果在 一个函数,该名称空间将是“未优化的”,即不使用 局部数组。因为exec()现在是一个普通函数,所以编译器会 不知道“exec”可能绑定到什么,因此无法处理 特别是

由于
global().update(…)
工作,以下代码将在根命名空间中工作(即,在任何函数之外),因为locals()与根命名空间中的globals()相同:

locals().update({'a':3, 'b':4})
print(a, b)
但这在函数内部不起作用

然而,作为黑客级Python程序员,我们可以使用
sys.\u getframe(1).f\u locals
而不是
locals()
。根据我到目前为止在Python 3上的测试,以下代码始终有效:

def f1():
  sys._getframe(1).f_locals.update({'a':3, 'b':4})
  print(a, b)

f1()

但是,
sys.\u getframe(1).f\u locals
在根命名空间中不起作用。

为什么要这样做?我懂了。非常感谢。那么如何更新函数中变量的局部字典呢?这就是我想要的。你一开始想要达到什么?更好地了解您需要什么将有助于我们帮助您:)例如,实现一些不错的故障恢复机制。当程序失败并重新启动时,它调用此函数从文件中读取字典并更新局部变量。这样,用户在编写程序时就可以像往常一样简单地初始化变量,然后调用updatelocals函数。谢谢!但是我在函数内部打印了
a
,为什么它仍然失去作用域?@shaoyl85:这就是为什么它们被称为局部变量。当控件超出函数范围时,这样的变量不存在。通过传递
locals()。但是改变它不会改变调用函数中的原始局部变量我想当调用
UpdateLocals
时,函数
TestUpdateLocals
还没有完成执行,所以“局部变量字典”仍然在内存中的某个地方。我可以做一些粗制滥造的事情,比如构造一些语句字符串来手动提取字典中的值,并使用它们来设置局部变量