【问题标题】:Python defaultdict that does not insert missing values不插入缺失值的 Python defaultdict
【发布时间】:2013-07-31 04:25:36
【问题描述】:

所以defaultdict documentation 提到,如果缺少某个项目,default_factory 返回的值“被插入到键的字典中,并返回。”这在大多数情况下都很棒,但在这种情况下,我真正想要的是返回但 插入到 defaultdict 中的值。

我想我可能可以继承 defaultdict 并覆盖...我猜__missing__?不确定。解决此问题的最佳方法是什么?

提前致谢。

【问题讨论】:

    标签: python collections defaultdict


    【解决方案1】:

    你可以继承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 路由来获得副本支持。谢谢!
    • 我可以为d.pop("unloaded_key")设置一个默认值吗?
    • @Lerner: dict.pop() 采用第二个参数作为默认值。 dict.pop()不会咨询__missing__,就像大多数其他方法一样;只有dict.__getitem__ 可以(所以d[missingkey])。
    • @MartijnPieters 我希望存在一个神奇的函数,通过它我可以为 dict.pop("missingkey") 等其他方法设置默认值。 :( 有可能吗?
    • @Lerner:没有。只需创建自己的;你已经继承了dict,所以只需添加def pop(self, *args): try: return super().pop(*args) except KeyError: return self.__missing__()。如果__missing__先设置字典中的键,则根据需要进行调整。
    【解决方案2】:

    它甚至比子类化更简单。当 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 else 在代码中,所以它仍然是合理的原版 dict :-)
    • 澄清一下,你是不是在使用d[key] += 1 插入default+1d[key],同时打算value = d[key] 返回默认值而不修改字典?
    • d[key] 会插入默认键 (0),d.get(key, 0) 不会
    猜你喜欢
    • 2016-10-06
    • 2020-08-22
    • 2018-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-15
    • 1970-01-01
    相关资源
    最近更新 更多