从函数内部更新局部变量

sha*_*l85 6 python

我想编写一个函数来接收本地命名空间字典并更新它。像这样的东西:

def UpdateLocals(local_dict):
  d = {'a':10, 'b':20, 'c':30}
  local_dict.update(d)
Run Code Online (Sandbox Code Playgroud)

当我从交互式 python shell 调用这个函数时,它工作正常,如下所示:

a = 1
UpdateLocals(locals())

# prints 20
print a
Run Code Online (Sandbox Code Playgroud)

但是,当我UpdateLocals从函数内部调用时,它不会执行我期望的操作:

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

# prints 1
TestUpdateLocals()
Run Code Online (Sandbox Code Playgroud)

我怎样才能使第二个案例像第一个案例一样工作?

更新:

Aswin的解释很有道理,对我很有帮助。但是我仍然想要一种更新局部变量的机制。在找到一种不太丑陋的方法之前,我将执行以下操作:

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

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

当然,字符串语句的构造可以自动化,并且可以对用户隐藏细节。

xua*_*g84 9

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

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

目前,globals().update(...)立即生效但locals().update(...)不起作用,因为Python文档说:

默认局部变量的行为如下面函数 locals() 中所述:不应尝试修改默认局部变量字典。如果您需要在函数 exec() 返回后查看代码对局部变量的影响,请传递显式局部变量字典。

Python之所以这样设计,是为了优化,将exec语句变成函数:

动态修改函数的局部变量是不可能的,否则会产生一些后果:通常,函数局部变量不存储在字典中,而是存储在数组中,其索引是在编译时根据已知的区域设置确定的。这至少与 exec 添加的新局部变量发生冲突。旧的 exec 语句规避了这一点,因为编译器知道,如果函数中发生没有全局/局部参数的 exec,则该命名空间将是“未优化的”,即不使用局部数组。由于 exec() 现在是一个普通函数,编译器不知道“exec”可能绑定到什么,因此不能特殊对待。

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

locals().update({'a':3, 'b':4})
print(a, b)
Run Code Online (Sandbox Code Playgroud)

但这在函数内部不起作用。

然而,作为黑客级的Python程序员,我们可以sys._getframe(1).f_locals使用locals(). 根据我迄今为止的测试,在 Python 3 上,以下代码始终有效:

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

f1()
Run Code Online (Sandbox Code Playgroud)

但是,sys._getframe(1).f_locals在根命名空间中不起作用。


Asw*_*esh 0

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

因此,函数中 locals() 的原始值没有改变 UpdateLocals

PS:这可能与你的问题无关,但在Python中使用驼峰式大小写并不是一个好的做法。尝试使用其他方法。

update_locals()代替UpdateLocals()

编辑要回答评论中的问题:

有一种东西叫做系统堆栈。该系统堆栈在代码执行过程中的主要工作是管理局部变量,确保被调用函数执行完成后控制权返回到正确的语句等,

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

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