kwargs переопределение подкласса dict


Минимальный пример выглядит следующим образом:

class sdict(dict):
    class dval:
        def __init__(self, val):
            self.val = val

    def __init__(self, args):
        dictionary = dict(args)
        for k,v in dictionary.items():
            self[k] = v

    def __setitem__(self,key,value):
         try:                   self[key].val = value
         except KeyError:       dict.__setitem__(self,key,self.dval(value))
    def __getitem__(self,key):
         return dict.__getitem__(self,key).val

Теперь я могу использовать этот класс внутри контейнера для переопределения присваиваемого материала:

class cont(object):
    def __init___(self):
        self._mydict = sdict(())
    @property
    def mydict(self):
        return self._mydict
    @mydict.setter
    def mydict(self,dict_initializor):
        self._mydict = sdict(dict_initializor)
        return self.mydict

Я использую это, чтобы мой контейнер содержал словарь с указательными примитивами (т. е. изменяемыми в языке python), но всякий раз, когда я извлекаю элемент, я получаю сам примитив. В моем случае поплавки, которые я умножаю, складываю и т. д... Добавление __ул.__/__репр__ функций делает эту работу для печати, но для отладки это опущено.

Это хорошо работает почти везде, за исключением передачи этого с помощью kwargs:

def test(a,b): return a*b
c = cont()
c.mydict = {'a':1,'b':2}
print c.mydict['a']+c.mydict['b'],type(c.mydict['a']+c.mydict['b'])
print test(**c.mydict)

Вывод:

3 <type 'int'>
Traceback (most recent call last):
  File "D:kabanusworkspacepy-modulestest.py", line 32, in <module>
    print test(**c.mydict)
  File "D:kabanusworkspacepy-modulestest.py", line 28, in test
    def test(a,b): return a*b
TypeError: unsupported operand type(s) for *: 'instance' and 'instance'

Очевидно, что процедура распаковки не использует _ _ getitem__ для создания значений ключевых слов. Я также попытался переопределить значения () и элементы () без успеха. Затем я установил все методы dict, не определенные мной, в None, чтобы увидеть, вызваны ли они - также не имеет успеха.

Итог - Как вы получаете * * kwargs распаковки, чтобы использовать _ _ getitem__ или некоторые другие метод?
Возможно ли это вообще?

Я также хочу избежать определения mul, add, div и так далее, если это возможно в классе dval.

1 2

1 ответ:

Нашел ответ здесь, и должен быть способ, чтобы сделать это легче найти: использует ли распаковка аргументов итерацию или получение элементов?

Резюме: Наследование от builtins (dict, list...) проблематично, поскольку python может полностью игнорировать ваш python API (как это было для меня)и использовать базовый C. Это происходит при распаковке аргументов.

Решение: используйте доступные абстракции. В моем примере добавьте:

from UserDict import UserDict

И заменить все вхождения "dict" в коде на UserDict. Это решение должно быть верным для списков и кортежей.