【发布时间】:2012-04-18 21:43:35
【问题描述】:
我觉得我最近看到了一种方法。假设我有一个空字典,我想在该空字典内的嵌套字典中设置一个值,但显然该嵌套字典尚未创建。是否有一种单行方式来创建中间键?这就是我想做的:
mydict = {}
mydict['foo']['bar']['foobar'] = 25
如果您执行此代码,您将收到“foo”的 KeyError 异常。有创建中间键的功能吗?
谢谢。
【问题讨论】:
标签: python dictionary
我觉得我最近看到了一种方法。假设我有一个空字典,我想在该空字典内的嵌套字典中设置一个值,但显然该嵌套字典尚未创建。是否有一种单行方式来创建中间键?这就是我想做的:
mydict = {}
mydict['foo']['bar']['foobar'] = 25
如果您执行此代码,您将收到“foo”的 KeyError 异常。有创建中间键的功能吗?
谢谢。
【问题讨论】:
标签: python dictionary
from collections import defaultdict
recursivedict = lambda: defaultdict(recursivedict)
mydict = recursivedict()
当您访问mydict['foo'] 时,它会将mydict['foo'] 设置为另一个recursivedict。它实际上也会为mydict['foo']['bar']['foobar'] 构造一个recursivedict,但随后将其分配给25 会被丢弃。
【讨论】:
mydict['foo'] = 15⏎ mydict['foo']['bar']['foobar'] = 25 上中断。在大型代码库中,OP 无法记住他之前分配的值。
__getitem__ 围绕存储的元素返回包装器,覆盖该元素的 __getitem__,这会使将列表或其他任何内容放入字典中变得很棘手。
另一种选择 - 根据您的用途,使用元组作为键而不是嵌套字典:
mydict = {}
mydict['foo', 'bar', 'foobar'] = 25
除非您想在任何时候获取树的分支(在这种情况下您无法获取 mydict['foo']),否则这将非常有效。
如果您知道要嵌套多少层,也可以使用functools.partial 代替 lambda。
from functools import partial
from collections import defaultdict
tripledict = partial(defaultdict, partial(defaultdict, dict))
mydict = tripledict()
mydict['foo']['bar']['foobar'] = 25
有些人觉得这比同等的基于 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
尽管与往常一样,在您知道存在瓶颈之前进行优化是没有意义的,所以在最快的之前选择最有用和可读的。
【讨论】:
prefix = ('foo', 'bar'); l = len(prefix); branch = { k[l:]: v for k, v in mydict.items() if k[:l] == prefix} 之类的方式获取树枝——尽管这需要遍历所有键。
dicts。
不知道你为什么想要,但是:
>>> 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}})})
【讨论】: