使用带有 __getitem__ 的 super 与下标

Using super with __getitem__ versus subscript

我正在写一个 dict,它只有正整数元组作为键。如果键未知并且元组的元素之一是 1,查找应该 return 默认值 0。任何其他未知密钥应引发 KeyError.

这很好用:

class zeroDict(dict):
    '''
    If key not in dict and an element of the tuple is 
    a 1, impute the value 0.
    '''    
    def __init__self():
        super().__init__()
    def __getitem__(self, key):
        try:
            return super().__getitem__(key)
        except KeyError:
            if 1 in key:
                return 0
            else:
                raise   

这不是:

class zDict(dict):
    '''
    If key not in dict and an element of the tuple is 
    a 1, impute the value 0.
    '''    
    def __init__self():
        super().__init__()
    def __getitem__(self, key):
        try:
            return super()[key]
        except KeyError:
            if 1 in key:
                return 0
            else:
                raise  

当我尝试从 zDict 中读取值时,我得到 TypeError: 'super' object is not subscriptable

实现之间的唯一区别是 zeroDict 表示

return super().__getitem__(key) 

zDict 表示

return super()[key]

然而,help(dict.__getitem__) 打印

__getitem__(...)
    x.__getitem__(y) <==> x[y]   

这似乎是说这两种说法是等价的。这里发生了什么?

正如其他人所解释的,super() 在这里不起作用的原因是因为它 returns 一个 超级对象 ,它是一个代理对象处理将点属性访问分派到方法解析顺序中的下一个 class。

也就是说,您不应该在这里覆盖 __getitem__,python 数据模型提供了一些东西只是为了这种情况,它是__missing__ method:

object.__missing__(self, key)

implement self[key] for dict subclasses when key is not in the dictionary.Called by dict.__getitem__()

所以,做这样的事情:

class ZeroDict(dict):
    def __missing__(self, key):
        if 0 in key:
            return 0
        else:
            raise KeyError(key)

以及演示:

>>> class ZeroDict(dict):
...     def __missing__(self, key):
...         if 0 in key:
...             return 0
...         else:
...             raise KeyError(key)
...
>>> d = ZeroDict()
>>> d[(1, 0)] = 'foo'
>>> d
{(1, 0): 'foo'}
>>> d[1, 0]
'foo'
>>> d[1, 1]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __missing__
KeyError: (1, 1)
>>> d[0, 1]
0
>>>