Thin proxy class for hashables I need some kind of thin wrapper object to mark dictionary keys, like:

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


And these wrappers should behave like the wrapped object (comparison, hashing, etc):

marked = Required('name')
marked == 'name'  #-&gt; True
d[marked] = 'hello'
d['name']  #-&gt; 'hello'


With a single additional property: it should remember the added class:

isinstance(marked, Required)  #-&gt; True




I dislike those heavyweight Proxy Patterns which mimic all special properties and thinking of the following idea instead:

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)


This basically instantiates the type again, but with an additional base, and seems to work:

v = 'abc'  # Wrapped value
vt = type(v)  # Wrapped value type
w = Wrapper(v)

assert w == v  # equality
assert isinstance(w, vt)  # type matches
assert isinstance(w, Wrapper)  # and is Wrapper
assert hash(w) == hash(v)  # hash matches (required for dict keys)


Can you think of any disadvantages of this approach?
You asked, "Can you think of any disadvantages of this approach?" One obvious problem is that this requires you to construct a new class each time the wrapper is called, which potentially ends up wasting a lot of memory. So you would want to cache and reuse these classes.

class Wrapper(object):
    # A map from (value type, wrapper class) to wrapped class
    __cache = {}

    def __new__(cls, value):
        value_type = type(value)
        bases = value_type, cls
        try:
            wrapper_class = cls.__cache[bases]
        except KeyError:
            wrapper_class = type(value_type.__name__, bases, {})
            cls.__cache[bases] = wrapper_class
        return wrapper_class(value)


Note that this is a rare case where we actually want to use a private name — the idea is to avoid a name clash when wrapping a class that already has a cache (or _cache, or whatever name we pick) attribute.

I can't help feeling, though, that Martijn Pieters is right in the Stack Overflow version of this question: if you just want to proxy a dictionary key, then you just need to proxy the __eq__ and __hash__ special methods. Keep it simple!