Python 2.6.5 defaultdict覆盖__setitem__无限递归

igg*_*ggy 3 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
Run Code Online (Sandbox Code Playgroud)

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

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

jon*_*rpe 5

这是__missing__导致问题的原因,并注意到:

  1. 没有必要定义__init__它是否调用超类; 和
  2. 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)
Run Code Online (Sandbox Code Playgroud)

那么为什么调用__missing__call会__setitem__导致递归呢?这种方法不只是告诉你是否key遗漏 ; 根据文件(强调我的):

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

__missing__这实际上把默认值到字典如果密钥已不存在,这意味着它必须调用__setitem__这样做.