Тонкий прокси-класс для хеш-таблиц


Мне нужен какой-то тонкий объект-обертка для обозначения ключей словаря, например:

d = {
  Required('name'): str,
  Optional('age'): int,
}

И эти обертки должны вести себя как обернутый объект (сравнение, хэширование и т. д.):

marked = Required('name')
marked == 'name'  #-> True
d[marked] = 'hello'
d['name']  #-> 'hello'

С одним дополнительным свойством: он должен помнить добавленный класс:

isinstance(marked, Required)  #-> True

И добавленный класс должен иметь пользовательские методы.

На самом деле это что-то вроде микширования хэшируемых объектов.


Мне не нравятся эти супертяжелые Прокси-паттерны , которые имитируют все специальные свойства и мышление следующей идеи вместо этого:

class Wrapper(object):
    def __new__(cls, value):
        value_type = type(value)
        Type = type(
            value_type.__name__,  # same name
            (cls, value_type),  # Wrapper + bases
            {})
        Type.__new__ = value_type.__new__  # prevent recursion
        return Type(value)

    # Override method
    def __repr__(self):
        return 'Wrapper({})'.format(self)

Лучшие идеи?

1 2

1 ответ:

Ваш Wrapper класс будет работать, да. Однако, если все, что вам нужно, - это оболочка, которая будет действовать как заменяющий ключ с дополнительными методами, тогда я просто создам выделенный класс вместо этого. явное здесь лучше, чем неявное .

Этот класс должен только прокси-сервер __eq__ и еще __hash__ Методы:

class HashableProxy(object):
    def __init__(self, wrapped):
        self._wrapped = wrapped

    def __eq__(self, other):
        return self._wrapped == other

    def __hash__(self):
        return hash(self._wrapped)

class Required(HashableProxy):
    pass

class Optional(HashableProxy):
    pass

Вы можете добавить методы к этому по мере необходимости.

Демо:

>>> marked = Required('name')
>>> marked == 'name'
True
>>> d = {}
>>> d[marked] = 'hello'
>>> d['name']
'hello'
>>> isinstance(marked, Required)
True