将字典加载到本地范围的方法之间的差异[重复]
Posted
技术标签:
【中文标题】将字典加载到本地范围的方法之间的差异[重复]【英文标题】:Differences between methods for loading a dictionary into the local scope [duplicate] 【发布时间】:2019-12-08 01:20:20 【问题描述】:在我们的代码中有一个地方,我们必须将字典的内容加载到本地范围的变量中。我知道这通常不是一个好主意,但是.. 原因。
在对类似问题 (Python: load variables in a dict into namespace) 的各种回答中,似乎有几种方法可以做到这一点,我想知道以下两种方法之间是否存在显着差异。
(注意,我只关注将键值对直接加载到本地范围的答案,而不是将它们加载到命名空间或类似对象的方法)
the_dict = 'x': 1', 'y': 'foo'
方法一:
for k, v in the_dict.items():
exec('k = v'.format(k=k))
方法二:
locals().update(the_dict)
最后一种方法似乎最简单,但我不确定是否有任何我没有看到的问题或陷阱。字典的值可以是任意类型,包括异常等对象。
如果相关,这是针对 Python 2.7
【问题讨论】:
方法 2 更安全,而且几乎可以肯定更快(因为update()
或多或少是一个原子操作,因此减少了完整 for
循环的开销以及执行时间exec
函数)。
与您链接到的问题中的pointed out 一样,方法2 does not work at all。方法 1 是更新函数局部变量的唯一方法(尽管它丑陋且缓慢)。但即使这样也只能在 Python 2 中使用,因为 exec
在 Python 3 中不再是一个语句。所以,由于这个问题没有问任何以前没有回答过的问题,它看起来应该作为一个副本关闭。
【参考方案1】:
正如您所说,这不仅是一个坏主意 - 它在 Python 中根本行不通。 至少对于“本地”意味着函数范围的“本地范围”来说不是。
TL;DR:如果您的“本地范围”是**模块范围,只需更新 locals()
就足够了。如果您的“本地范围”是一个功能块,更新locals()
通常对于动态创建局部变量是没有用的。然而,在 Python 2 中,在函数体中使用 exec
将禁用快速局部优化,并且使用的字节码操作将是 LOAD NAME
,这将匹配在 exec
体中定义的 vairbales。因此,在函数内部,您必须使用 exec
选项(尽管,如果函数包含单个 exec 语句,更新 locals
应该可以工作,因为优化会被禁用)
它可以用于模块范围(无论如何在 Python 中称为global
),并且
使用类体作为命名范围。
这是因为在函数内部,出于速度原因,从固定槽中使用局部变量,这会影响名称->局部变量(locals()
.返回的字典)的映射。因此,如果您可以在 locals()
dict 中创建新的“局部变量”,如果在下面一行的代码中尝试访问该变量,那么在同一函数体中,该代码将被编译以尝试获取来自globals
的变量 - 即:
a = "global"
def b():
locals()["a"] = "local"
print(a)
结果:
>>> b()
global
另一方面,eval
几乎不需要 - 当您获得一个可以工作的范围时,更新正确的字典已经可以工作了。如上所述,可以为此使用类体,其优点是它可以直接作为命名空间工作:
>>> the_dict = 'x': '1', 'y': 'foo'
>>> class A:
... locals().update(the_dict)
...
>>> A.x
'1'
>>> A.y
'foo'
这当然是“推荐”的。请注意,在极端情况下创建类可能会产生一些副作用(例如,如果 dict 中的一个对象具有__get__
方法,它将被用作描述符)。
【讨论】:
(顺便提一下:你现在真的不应该使用 Python2) 感谢您在答案第一部分提供的信息。我不知道 locals() 字典只是本地命名空间的副本(这在文档中已明确说明。但是,我不赞成答案,因为它忽略了我陈述 的问题部分“...将值直接加载到本地范围,而不是将它们加载到命名空间或类似的方法”。我无法修改访问这些变量的代码以包括对类的使用。此外,关于不使用 Python 2 的评论既没有回答问题,也没有提供有用的信息。 所以,我更新了答案。如果您愿意,如果答案中没有错误,写这些答案确实需要时间才能让他们投反对票。您可以在不投票的情况下发表评论,要求额外澄清。关于 Python 2 的评论是有原因的,而且你知道它是什么——它正在停产,计划于 2020 年 1 月 1 日硬关闭。 @jsbueno 可以动态地创建新的函数局部变量。可以使用exec
语句来完成(在 Python 2 中,但不是 3 中),如问题所示(即方法 1)。
是的,对不起,我忘记了。我认为它现在已修复。以上是关于将字典加载到本地范围的方法之间的差异[重复]的主要内容,如果未能解决你的问题,请参考以下文章