Python 2.6.5 defaultdict覆盖__setitem__无限递归

时间:2015-07-03 12:33:38

标签: python dictionary

我想实现一个字典,可以对插入的键进行某些检查,例如请参阅下面的内容:

from collections import defaultdict

class CheckingDict(defaultdict):

    def __init__(self, *args, **kwargs):
        super(CheckingDict, self).__init__(*args, **kwargs)

    def __setitem__(self, key, value):
        if not super(CheckingDict, self).__missing__(key):
            raise ValueError("Key {key} is already present".format(key=key))
        else:
            return defaultdict.__setitem__(self, key, value)

a = CheckingDict(lambda: None)
a[1] = 1

上面代码的问题是给了我无限递归。所以问题是为什么以及如何正确地做到这一点?

我不想使用合成,因为要获得defaultdict的所有功能,我需要编写更多代码。

1 个答案:

答案 0 :(得分:5)

导致问题的__missing__,请注意:

  1. 如果调用超类,那么定义__init__是没有意义的。和
  2. 实际设置项目时,您没有使用super
  3. 工作实施:

    class CheckingDict(defaultdict):
    
        def __setitem__(self, key, value):
            if key in self:
                raise ValueError("Key {!r} is already present".format(key))
            super(CheckingDict, self).__setitem__(key, value)
    

    那么为什么调用__missing__调用__setitem__,导致递归呢?该方法不会告诉您key是否缺失;每the documentation(强调我的):

      

    如果default_factory不是None,则在没有参数的情况下调用[__missing__]   提供给定键的默认值,插入此值   密钥的字典,并返回。

    如果密钥已经存在,那么__missing__实际上将默认值放入字典中,这意味着它必须调用__setitem__来执行此操作。< / p>