Класс python, который действует как отображение для ** распаковки

Без подкласса dict, что класс должен считаться сопоставлением, чтобы его можно было передать методу с **

from abc import ABCMeta

class uobj:
    __metaclass__ = ABCMeta

uobj.register(dict)

def f(**k): return k

o = uobj()
f(**o)

# outputs: f() argument after ** must be a mapping, not uobj

По крайней мере, до того момента, когда он выдает ошибки отсутствующей функциональности сопоставления, я могу начать реализовывать.

Я рассмотрел эмуляцию типов контейнеров, но просто определение магических методов не имеет никакого эффекта, и использование ABCMeta для переопределения и регистрации в виде dict проверяет утверждения как подкласс, но не имеет значения isinstance (o, dict). В идеале, я даже не хочу использовать ABCMeta.

Ответ 1

Способы __getitem__() и keys() будут достаточны:

>>> class D:
        def keys(self):
            return ['a', 'b']
        def __getitem__(self, key):
            return key.upper()


>>> def f(**kwds):
        print kwds


>>> f(**D())
{'a': 'A', 'b': 'B'}

Ответ 2

Если вы пытаетесь создать сопоставление - не просто удовлетворяете требованиям для передачи функции - тогда вы действительно должны наследовать от collections.Mapping. Как описано в документации, вам нужно просто реализовать:

__getitem__
__len__
__iter__

Mixin выполнит для вас все остальное: __contains__, keys, items, values, get, __eq__ и __ne__.