Python中的defaultdict不插入缺失值

19

因此,defaultdict文档提到,如果一个条目缺失,则由default_factory返回的值“被插入到键的字典中并返回”。这在大多数情况下都很好,但是在这种情况下,我实际上想要的是返回该值,但是不要将其插入到defaultdict中。

我想我可能可以继承defaultdict并覆盖...我猜是 __missing__ ? 不确定。怎样做最好?

提前感谢。

2个回答

18
你可以创建 dict 的子类并实现 __missing__:
class missingdict(dict):
    def __missing__(self, key):
        return 'default'  # note, does *not* set self[key]

演示:

>>> d = missingdict()
>>> d['foo']
'default'
>>> d
{}

你也可以以defaultdict为基类创建子类,这样就能获得工厂处理功能以及复制和pickle支持:

from collections import defaultdict

class missingdict(defaultdict):
    def __missing__(self, key):
        return self.default_factory() 

演示:

>>> from collections import defaultdict
>>> class missingdict(defaultdict):
...     def __missing__(self, key):
...         return self.default_factory() 
... 
>>> d = missingdict(list)
>>> d['foo']
[]
>>> d
defaultdict(<type 'list'>, {})

但是,正如您所看到的,__repr__ 的名称是错误的。


太好了。我可能会选择defaultdict路线来获得复制支持。谢谢! - Chad
我可以为 d.pop("unloaded_key") 设置默认值吗? - Lerner Zhang
1
@Lerner:dict.pop()方法需要第二个参数来设置默认值。与大多数其他方法不同,dict.pop()方法不会调用__missing__方法;只有dict.__getitem__方法才会(例如d[missingkey])。 - Martijn Pieters
@MartijnPieters,我希望存在一种神奇的函数,可以为其他方法设置默认值,比如dict.pop("missingkey")。:( 这可能吗? - Lerner Zhang
2
@Lerner:没有。只需创建您自己的;您已经在子类化dict,因此只需添加def pop(self, *args): try: return super().pop(*args) except KeyError: return self.__missing__()。如果__missing__首先在字典中设置键,则根据需要进行调整。 - Martijn Pieters
@MartijnPieters 你是个很棒的人。 - Lerner Zhang

0

这比子类化还要简单。虽然 dict[key] 会添加键,但是 dict.get(key, default=None) 不会将键添加到字典中:

import collections

d = collections.defaultdict(int)

assert d['test1'] == 0

print(d)
# defaultdict(<class 'int'>, {'test1': 0})

assert d.get('test2', 0) == 0
# for a more generic version, use `d.default_factory()` instead of 0

print(d)
# defaultdict(<class 'int'>, {'test1': 0})
# => did NOT insert a key for 'test2' =)

如果有人反对使用DEFAULTdict的目的,那么在某种程度上是的。但在我的特定用例中,我还在代码的其他地方利用了defaultdict update à la d[key] += 1,因此仍然比普通字典更合理 :-) - xjcl
只是为了明确,你是否使用d[key] += 1default+1插入到d[key],同时希望value = d[key]返回默认值而不修改字典? - Elias Hasle
d[key] 会插入默认键(0),而 d.get(key, 0) 则不会。 - xjcl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接