默认字典的默认字典?
有没有办法让 defaultdict(defaultdict(int))
以使以下代码正常工作?
for x in stuff:
d[x.a][x.b] += x.c_int
d
需要根据 xa
和 xb
元素进行临时构建。
我可以使用:
for x in stuff:
d[x.a,x.b] += x.c_int
但随后我将无法使用:
d.keys()
d[x.a].keys()
Is there a way to have a defaultdict(defaultdict(int))
in order to make the following code work?
for x in stuff:
d[x.a][x.b] += x.c_int
d
needs to be built ad-hoc, depending on x.a
and x.b
elements.
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()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
是的,就像这样:
当您尝试访问不存在的密钥时,将调用
defaultdict
的参数(在本例中为lambda: defaultdict(int)
) 。它的返回值将被设置为该键的新值,这意味着在我们的例子中,d[Key_doesnt_exist]
的值将是defaultdict(int)
。如果您尝试从最后一个defaultdict即
d[Key_doesnt_exist][Key_doesnt_exist]
访问一个键,它将返回0,这是最后一个defaultdict即int()的参数的返回值
。Yes like this:
The argument of a
defaultdict
(in this case islambda: defaultdict(int)
) will be called when you try to access a key that doesn't exist. The return value of it will be set as the new value of this key, which means in our case the value ofd[Key_doesnt_exist]
will bedefaultdict(int)
.If you try to access a key from this last defaultdict i.e.
d[Key_doesnt_exist][Key_doesnt_exist]
it will return 0, which is the return value of the argument of the last defaultdict i.e.int()
.defaultdict 构造函数的参数是将调用以构建新元素的函数。那么让我们使用 lambda 吧!
从 Python 2.7 开始,有一个使用 Counter 的更好的解决方案:
一些额外的功能
有关详细信息,请参阅 PyMOTW - 集合 - 容器数据类型 和 Python 文档 - 集合
The parameter to the defaultdict constructor is the function which will be called for building new elements. So let's use a lambda !
Since Python 2.7, there's an even better solution using Counter:
Some bonus features
For more information see PyMOTW - Collections - Container data types and Python Documentation - collections
之前的答案已经解决了如何制作两层或n层
defaultdict
。在某些情况下,您想要一个无限的:用法:
Previous answers have addressed how to make a two-levels or n-levels
defaultdict
. In some cases you want an infinite one:Usage:
我发现使用
partial
稍微优雅一些:当然,这与 lambda 相同。
I find it slightly more elegant to use
partial
:Of course, this is the same as a lambda.
作为参考,可以通过以下方式实现通用嵌套
defaultdict
工厂方法:深度定义在使用
default_factory
中定义的类型之前嵌套字典的数量。例如:
For reference, it's possible to implement a generic nested
defaultdict
factory method through:The depth defines the number of nested dictionary before the type defined in
default_factory
is used.For example:
其他人已经正确回答了您如何使以下内容发挥作用的问题:
另一种方法是使用元组作为键:
这种方法的好处是它很简单并且可以轻松扩展。如果您需要三层深度的映射,只需使用三项元组作为键。
Others have answered correctly your question of how to get the following to work:
An alternative would be to use tuples for keys:
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.
defaultdict(lambda: defaultdict(int))
有一个缺陷,即它对pickle
不友好,这要归功于lambda
。虽然您可以全局定义默认函数,例如:解决这个问题,但这是相当冗长的。幸运的是,如果没有这样的方式,以
pickle
友好的方式完成这项工作非常容易:这使得模板为空
defaultdict(int)
,并传递一个绑定的copy
方法将其作为工厂函数。因为defaultdict
和int
是可pickle的,所有可pickle对象的绑定方法也是如此,这使得结构完全可pickle,无需任何自定义定义或额外的导入。在某些版本的 Python 上,它比等效的 lambda 性能更高(取决于最近的优化工作集中在哪里),但即使不是这样,性能也相当,而且不再多了。冗长,所以即使不关心酸洗,这也是我的首选方法,仅仅是因为这意味着如果/当酸洗变得重要时我不需要改变方法。defaultdict(lambda: defaultdict(int))
has a flaw, which is that it isn'tpickle
friendly, thanks to thelambda
. While you could define the default function globally, e.g.:to work around this, that's rather verbose. Luckily, it's pretty easy to make this work in a
pickle
-friendly way without that:That makes a template empty
defaultdict(int)
, and passes a boundcopy
method from it as the factory function. Becausedefaultdict
andint
are pickleable, as are all bound methods of pickleable objects, that renders the structure fully pickleable without any custom definitions or additional imports. On some versions of Python, it's more performant than the equivalentlambda
(depending on where the recent optimization efforts have been centered), but even when it isn't, the performance is comparable, and it's no more verbose, so it's my preferred approach even when pickling isn't a concern, simply because it means I don't need to change approaches if/when pickling becomes important.