Python:将字典中的变量加载到命名空间中
我想在函数外部使用一堆在函数中定义的局部变量。所以我在返回值中传递x=locals()
。
如何将该字典中定义的所有变量加载到函数外部的命名空间中,这样我就可以简单地使用 variable
来访问该值,而不是使用 x['variable']
来访问该值代码>.
I want to use a bunch of local variables defined in a function, outside of the function. So I am passing x=locals()
in the return value.
How can I load all the variables defined in that dictionary into the namespace outside the function, so that instead of accessing the value using x['variable']
, I could simply use variable
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
您可以使用 argparse.Namespace 来代替创建自己的对象:
执行相反的操作:
Rather than create your own object, you can use
argparse.Namespace
:To do the inverse:
考虑使用
Bunch
替代方案:因此,如果您有一个字典
d
并且希望使用语法x.foo
访问(读取)其值,而不是笨拙的d['foo']
,只需在函数内部和外部执行此操作即可 - 而且它比注入
d
更干净、更安全进入globals()
!记住 Python 之禅的最后一行……:Consider the
Bunch
alternative:so if you have a dictionary
d
and want to access (read) its values with the syntaxx.foo
instead of the clumsierd['foo']
, just dothis works both inside and outside functions -- and it's enormously cleaner and safer than injecting
d
intoglobals()
! Remember the last line from the Zen of Python...:这是导入变量的完全有效的情况
一个本地空间到另一个本地空间只要
一个人知道他/她在做什么。
我已经多次看到这样的代码被以有用的方式使用。
只是需要小心不要污染共同的全球空间。
您可以执行以下操作:
This is perfectly valid case to import variables in
one local space into another local space as long as
one is aware of what he/she is doing.
I have seen such code many times being used in useful ways.
Just need to be careful not to pollute common global space.
You can do the following:
将变量导入本地命名空间是一个有效的问题,并且经常在模板框架中使用。
从函数返回所有局部变量:
然后按如下方式导入:
Importing variables into a local namespace is a valid problem and often utilized in templating frameworks.
Return all local variables from a function:
Then import as follows:
Bunch 答案是好的,但缺乏递归和适当的
__repr__
和__eq__
内置函数来模拟你已经可以用字典做的事情。另外,递归的关键不仅是对字典进行递归,还要对列表进行递归,这样列表内的字典也会被转换。我希望这两个选项能够满足您的需求(对于更复杂的对象,您可能需要调整 __elt() 中的类型检查;这些主要是在 json 导入上进行测试的,因此非常简单的核心类型)。
repr(obj)
将返回Bunch({...})
,可以将其重新解释为等效对象。类型.SimpleNamespace
已经实现了__repr__
和__eq__
,您所需要的只是实现一个递归的__init__
方法:< em>RecursiveNamespace 类采用关键字参数,当然可以来自取消引用的字典(例如
**mydict
)现在让我们测试它们(
argparse.Namespace添加
进行比较,尽管它的嵌套字典是手动转换的):结果是:
虽然这些是不同的类,因为它们(
a
和b
)都有被初始化为等效的命名空间,并且其__eq__
方法仅比较命名空间 (self.__dict__
),比较两个命名空间对象返回True
。对于与 argparse.Namespace 进行比较的情况,出于某种原因,只有Bunch
有效,我不确定为什么(如果您知道,请发表评论,我没有进一步研究因为types.SimpleNameSpace
是一个内置实现)。您可能还会注意到,我使用
type(self)(...)
而不是使用类名进行递归 - 这有两个优点:首先可以重命名类,而无需更新递归调用,并且其次,如果该类是子类的,我们将使用子类名称进行递归。它也是__repr__
(type(self).__name__
) 中使用的名称。编辑 2021 年 11 月 27 日:
修改了
Bunch.__eq__
方法,使其能够安全地防止类型不匹配。添加/修改了可选的
__eq__
方法(已注释掉),以允许与原始dict
和argparse.Namespace(**dict)
进行比较(请注意,后者不是递归的,但仍然可以与其他类进行比较,因为无论如何子级别结构都会比较好)。The Bunch answer is ok but lacks recursion and proper
__repr__
and__eq__
builtins to simulate what you can already do with a dict. Also the key to recursion is not only to recurse on dicts but also on lists, so that dicts inside lists are also converted.These two options I hope will cover your needs (you might have to adjust the type checks in
__elt()
for more complex objects; these were tested mainly on json imports so very simple core types).repr(obj)
will returnBunch({...})
that can be re-interpreted into an equivalent object.types.SimpleNamespace
already implements__repr__
and__eq__
, all you need is to implement a recursive__init__
method:The RecursiveNamespace class takes keyword arguments, which can of course come from a de-referenced dict (ex
**mydict
)Now let's put them to the test (
argparse.Namespace
added for comparison, although it's nested dict is manually converted):The result is:
Although those are different classes, because they both (
a
andb
) have been initialized to equivalent namespaces and their__eq__
method compares the namespace only (self.__dict__
), comparing two namespace objects returnsTrue
. For the case of comparing withargparse.Namespace
, for some reason onlyBunch
works and I'm unsure why (please comment if you know, I haven't looked much further astypes.SimpleNameSpace
is a built-in implementation).You might also notice that I recurse using
type(self)(...)
rather than using the class name - this has two advantages: first the class can be renamed without having to update recursive calls, and second if the class is subclassed we'll be recursing using the subclass name. It's also the name used in__repr__
(type(self).__name__
).EDIT 2021-11-27:
Modified the
Bunch.__eq__
method to make it safe against type mismatch.Added/modified optional
__eq__
methods (commented out) to allow comparing with the originaldict
andargparse.Namespace(**dict)
(note that the later is not recursive but would still be comparable with other classes as the sublevel structs would compare fine anyway).为了扩展 Thomas 的想法,以下内容保留了任何支持列表到类型转换的可迭代对象的类型。
输出:
To extend Thomas's idea, the following preserves type of any supported iterable object that supports list-to-type conversion.
output:
使用以下代码片段 (PY2) 从我的 dict(yaml) 配置中创建递归命名空间:
Used following snippet (PY2) to make recursive namespace from my dict(yaml) configs:
总是有这个选项,我不知道这是最好的方法,但它确实有效。假设 type(x) = dict
There's Always this option, I don't know that it is the best method out there, but it sure does work. Assuming type(x) = dict