简体   繁体   English

设置嵌套的dict值并创建中间键

[英]Set nested dict value and create intermediate keys

I feel like I saw a way to do this recently. 我觉得最近我看到了一种方法。 Say I've got an empty dict and I want to set a value in a nested dict inside that empty dict, but obviously that nested dict hasn't been created yet. 假设我有一个空字典,我想在该空字典中的嵌套字典中设置一个值,但显然嵌套字典尚未创建。 Is there a 1-line way to create the intermediate keys? 是否有一种创建中间键的方法? This is what I want to do: 这就是我想要做的:

mydict = {}
mydict['foo']['bar']['foobar'] = 25

If you execute this code you'll get a KeyError exception for 'foo'. 如果执行此代码,您将获得'foo'的KeyError异常。 Is there a function to create intermediate keys? 是否有创建中间键的功能?

Thanks. 谢谢。

from collections import defaultdict
recursivedict = lambda: defaultdict(recursivedict)
mydict = recursivedict()

When you access mydict['foo'] , it sets mydict['foo'] to another recursivedict . 当你访问mydict['foo'] ,它mydict['foo']为另一个recursivedict It'll actually construct a recursivedict for mydict['foo']['bar']['foobar'] as well, but then it'll get thrown out by assigning that to 25 . 它实际上也会为mydict['foo']['bar']['foobar']构建一个recursivedict ,但是它会被分配给25来抛出它。

An alternative option - depending on your uses, is to use tuples as keys instead of nested dictionaries: 另一种选择 - 取决于您的用途,是使用元组作为键而不是嵌套字典:

mydict = {}
mydict['foo', 'bar', 'foobar'] = 25

This will work perfectly well unless you want to get a branch of the tree at any point (you can't get mydict['foo'] in this case). 这将非常有效,除非你想在任何一点获得树的分支(在这种情况下你不能得到mydict ['foo'])。

If you knew how many layers of nesting you want, you could also use functools.partial instead of lambda. 如果你知道你想要多少层嵌套,你也可以使用functools.partial而不是lambda。

from functools import partial
from collections import defaultdict

tripledict = partial(defaultdict, partial(defaultdict, dict))
mydict = tripledict()
mydict['foo']['bar']['foobar'] = 25

Which some people find more readable, and is faster to create instances of than the equivalent lambda-based solution: 有些人发现更具可读性,并且创建实例比基于lambda的等效解决方案更快:

python -m timeit -s "from functools import partial" -s "from collections import defaultdict" -s "tripledefaultdict = partial(defaultdict, partial(defaultdict, dict))" "tripledefaultdict()"
1000000 loops, best of 3: 0.281 usec per loop

python -m timeit -s "from collections import defaultdict" -s "recursivedict = lambda: defaultdict(recursivedict)" "recursivedict()"
1000000 loops, best of 3: 0.446 usec per loop

Although, as always, there is no point optimising until you know there is a bottleneck, so pick what is most useful and readable before what is fastest. 虽然一如既往,在知道存在瓶颈之前没有必要进行优化,因此在最快之前选择最有用和可读的内容。

Not sure why you'd want to, but: 不知道为什么你想要,但是:

>>> from collections import defaultdict as dd
>>> mydict = dd(lambda: dd(lambda: {}))
>>> mydict['foo']['bar']['foobar'] = 25
>>> mydict
defaultdict(<function <lambda> at 0x021B8978>, {'foo': defaultdict(<function <lambda> at 0x021B8618>, {'bar': {'foobar': 25}})})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM