覆盖字典 __getitem__ 魔术方法时出现递归错误?

Recursion Error on overriding the Dictionary __getitem__ magic-method?

我想要我的 getitem 方法到 return None,如果键不可用,还要添加具有值的键 None。如果密钥可用,则 return 值。

>>> class VariableDict(dict):

    def __getitem__(self, key):
        try:
            return self[key]
        except KeyError:
            self['key'] = None
            return None


>>> d = {'a': 1, 'b': 2}
>>> d = VariableDict(d)
>>> d
{'a': 1, 'b': 2}
>>> d['k']
Traceback (most recent call last):
  File "<pyshell#64>", line 1, in <module>
    d['k']
  File "<pyshell#60>", line 5, in __getitem__
    return self['key']
  File "<pyshell#60>", line 5, in __getitem__
    return self['key']
  File "<pyshell#60>", line 5, in __getitem__
    return self['key']
  [Previous line repeated 327 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object

我在这里遇到了什么问题,是否有其他方法可以解决我的问题。还请解释一下,我的代码有什么问题以及为什么会出现此 RecursionError。

基本上是因为这一行:

    return self['key']

将再次调用 VariableDict__getitem__ 方法,因此您的方法将继续调用自身而没有停止条件。您需要的是使用超类 __getitem__ 方法:

super().__getitem__(key)

注意:您正在使用'key'访问给定的项目,我认为您不是那个意思,因为self['key']将return 与 key.

的值无关的相同值

__getitem__ 方法是在字典中实现键查找的方法,因此如果不递归就无法执行 self['key']。相反,您可能想要调用您在 class 中覆盖的 __getitem__ 的原始实现。通常的方法是使用 super:

    try:
        return super().__getitem__('key')
    except KeyError:
        ...

您的代码可能还有其他问题。您使用了一个名为 key 的参数,但实际上并没有在您的代码中使用它。相反,您使用字符串 'key' 作为在字典中查找和设置的键。可能您想使用 key 而不是带引号的 'key'

如果在字典中找不到值,还有一种更好的方法来提供默认值。它没有很好的记录,但是 Python 字典可以定义一个 __missing__ 方法,如果存在,将在键查找失败时随时调用。该方法的返回值将是查找的结果,您也可以根据需要修改字典。因此,实现 class 的更好方法可能是:

class VariableDict(dict):
    def __missing__(self, key):
        self[key] = None            # note, I'm using key instead of 'key' here!
        return None