我想实现一个字典,可以对插入的键进行某些检查,例如请参阅下面的内容:
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
的所有功能,我需要编写更多代码。
答案 0 :(得分:5)
导致问题的__missing__
,请注意:
__init__
是没有意义的。和super
。工作实施:
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>