Использование супер с __getitem__ против индекса - PullRequest
0 голосов
/ 05 мая 2019

Я пишу dict, в котором в качестве ключей используются только кортежи натуральных чисел.Если ключ неизвестен и один из элементов кортежа - 1, поиск должен вернуть значение по умолчанию 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]   

, который, кажется, говорит, что эти два утверждения эквивалентны.Что здесь происходит?

1 Ответ

0 голосов
/ 05 мая 2019

Как объяснили другие, причина того, что super() здесь не работает, заключается в том, что он возвращает суперобъект , который является прокси-объектом, который обрабатывает диспетчеризацию доступа к пунктирному атрибуту для следующего класса в методепорядок разрешения.

При этом вам не следует переопределять __getitem__ здесь, модель данных Python предоставляет что-то только для этого случая , это __missing__ метод :

object.__missing__(self, key)

реализовать self[key] для подклассов dict, когда ключ отсутствует в словаре. Вызывается 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
>>>
...