本文翻译自:Python: defaultdict of defaultdict?
Is there a way to have a
defaultdict(defaultdict(int))
in order to make the following code work?
有没有一种方法使defaultdict(defaultdict(int))
可以使以下代码正常工作? for x in stuff:
d[x.a][x.b] += x.c_int
d
needs to be built ad-hoc, depending on
xa
and
xb
elements.
d
需要临时构建,具体取决于 xa
和 xb
元素。 I could use:
我可以使用:for x in stuff:
d[x.a,x.b] += x.c_int
but then I wouldn't be able to use:
但后来我将无法使用:d.keys()
d[x.a].keys()
#1楼
参考:https://stackoom.com/question/l6vY/Python-defaultdict的defaultdict
#2楼
Yes like this:
是这样的:defaultdict(lambda: defaultdict(int))
The argument of a
defaultdict
(in this case is
lambda: defaultdict(int)
) will be called when you try to access a key that doesn't exist.
当您尝试访问不存在的键时,将调用defaultdict
的参数(在本例中为 lambda: defaultdict(int)
)。 The return value of it will be set as the new value of this key, which means in our case the value of
d[Key_doesnt_exist]
will be
defaultdict(int)
.
它的返回值将设置为该键的新值,这意味着在我们的示例中d[Key_doesnt_exist]
的值将为 defaultdict(int)
。 If you try to access a key from this last defaultdict ie
d[Key_doesnt_exist][Key_doesnt_exist]
it will return 0, which is the return value of the argument of the last defaultdict ie
int()
.
如果您尝试从最后一个defaultdict即d[Key_doesnt_exist][Key_doesnt_exist]
访问密钥,它将返回0,这是最后一个defaultdict即 int()
的参数的返回值。 #3楼
The parameter to the defaultdict constructor is the function which will be called for building new elements.
defaultdict构造函数的参数是用于构建新元素的函数。So let's use a lambda !
因此,让我们使用lambda!>>> from collections import defaultdict
>>> d = defaultdict(lambda : defaultdict(int))
>>> print d[0]
defaultdict(<type 'int'>, {})
>>> print d[0]["x"]
0
Since Python 2.7, there's an even better solution using Counter :
从Python 2.7开始, 使用Counter有了一个更好的解决方案 :>>> from collections import Counter
>>> c = Counter()
>>> c["goodbye"]+=1
>>> c["and thank you"]=42
>>> c["for the fish"]-=5
>>> c
Counter({'and thank you': 42, 'goodbye': 1, 'for the fish': -5})
Some bonus features
一些额外功能>>> c.most_common()[:2]
[('and thank you', 42), ('goodbye', 1)]
For more information see PyMOTW - Collections - Container data types and Python Documentation - collections
有关更多信息,请参见PyMOTW-集合-容器数据类型和Python文档-集合#4楼
I find it slightly more elegant to use
partial
:
我发现使用partial
稍微优雅 partial
: import functools
dd_int = functools.partial(defaultdict, int)
defaultdict(dd_int)
Of course, this is the same as a lambda.
当然,这与lambda相同。#5楼
Others have answered correctly your question of how to get the following to work:
其他人已经正确回答了您有关如何使以下内容正常工作的问题:for x in stuff:
d[x.a][x.b] += x.c_int
An alternative would be to use tuples for keys:
一种替代方法是使用元组作为键:d = defaultdict(int)
for x in stuff:
d[x.a,x.b] += x.c_int
# ^^^^^^^ tuple key
The nice thing about this approach is that it is simple and can be easily expanded.
这种方法的好处是它很简单并且可以轻松扩展。If you need a mapping three levels deep, just use a three item tuple for the key.
如果您需要三个层次的映射,只需使用一个三项元组作为键。#6楼
For reference, it's possible to implement a generic nested
defaultdict
factory method through:
作为参考,可以通过以下方式实现通用的嵌套defaultdict
工厂方法: from collections import defaultdict
from functools import partial
from itertools import repeat
def nested_defaultdict(default_factory, depth=1):
result = partial(defaultdict, default_factory)
for _ in repeat(None, depth - 1):
result = partial(defaultdict, result)
return result()
The depth defines the number of nested dictionary before the type defined in
default_factory
is used.
在使用default_factory
定义的类型之前,深度定义了嵌套字典的数量。 For example:
例如:my_dict = nested_defaultdict(list, 3)
my_dict['a']['b']['c'].append('e')