"specialdict" module

Georg Brandl g.brandl at gmx.net
Mon Apr 4 12:51:31 EDT 2005


Michele Simionato wrote:
> About not using super: you might have problems in multiple inheritance.
> Suppose I want to use both your defaultdict and a thirdpartdict. A
> subclass
> 
> class mydict(defaultdict, thirdpartdict):
>    pass
> 
> would not work if thirdpartdict requires a non-trivial __init__ , since
> without super in defaultdict.__init__ you would just call dict.__init__
> and not thirdpartdict.

Right. I thought about a combined defaultdict/keytransformdict,
which seems to be easy to create with the current implementation:

class defaultkeytransformdict(defaultdict, keytransformdict):
    pass

At least I hope so. This is another argument against the initializing
of defaultfactory or keytransformer in __init__.

mfg
Georg

Here comes the current module (keytransformdict should be working now
for all dict methods):

# specialdict - subclasses of dict for common tasks
#

class NoDefaultGiven(Exception):
    pass

class defaultdict(dict):
    __slots__ = ['_default']

    def __init__(self, *args, **kwargs):
        self._defaulttype = 0

        super(defaultdict, self).__init__(*args, **kwargs)

    def setdefaultvalue(self, value):
        def defaultfactory():
            return value
        self._default = (defaultfactory, (), {})

    def setdefaultfactory(self, factory, *args, **kwargs):
        if not callable(factory):
            raise TypeError, 'default factory must be a callable'
        self._default = (factory, args, kwargs)

    def cleardefault(self):
        def defaultfactory():
            raise NoDefaultGiven
        self._default = (defaultfactory, (), {})

    def __getitem__(self, key):
        try:
            return super(defaultdict, self).__getitem__(key)
        except KeyError, err:
            try:
                return self.setdefault(key, self._default[0](*self._default[1], **self._default[2]))
            except NoDefaultGiven:
                raise err

class keytransformdict(dict):
    __slots__ = ['_transformer']

    def __init__(self, *args, **kwargs):
        self._transformer = lambda x: x

        super(keytransformdict, self).__init__(*args, **kwargs)

    def settransformer(self, transformer):
        if not callable(transformer):
            raise TypeError, 'transformer must be a callable'
        self._transformer = transformer

    def __setitem__(self, key, value):
        print "setitem"
        super(keytransformdict, self).__setitem__(self._transformer(key), value)

    def __getitem__(self, key):
        print "getitem"
        return super(keytransformdict, self).__getitem__(self._transformer(key))

    def __delitem__(self, key):
        super(keytransformdict, self).__delitem__(self._transformer(key))

    def has_key(self, key):
        return super(keytransformdict, self).has_key(self._transformer(key))

    def __contains__(self, key):
        return self.has_key(key)

    def get(self, key, default):
        return super(keytransformdict, self).get(self._transformer(key), default)

    def setdefault(self, key, default):
        return super(keytransformdict, self).setdefault(self._transformer(key), default)

    def pop(self, key, default):
        return super(keytransformdict, self).pop(self._transfomer(key), default)

    def update(self, other=None, **kwargs):
        if other is not None:
            if hasattr(other, "keys"):
                super(keytransformdict, self).update((self._transformer(k), other[k]) for k in other.keys())
            else:
                super(keytransformdict, self).update((self._transformer(k), v) for (k, v) in other)
        if kwargs:
            super(keytransformdict, self).update((self._transformer(k), v) for (k, v) in kwargs.iteritems())

class sorteddict(dict):
    def __iter__(self):
        for key in sorted(super(sorteddict, self).__iter__()):
            yield key

    def keys(self):
        return list(self.iterkeys())

    def items(self):
        return list(self.iteritems())

    def values(self):
        return list(self.itervalues())

    def iterkeys(self):
        return iter(self)

    def iteritems(self):
        return ((key, self[key]) for key in self)

    def itervalues(self):
        return (self[key] for key in self)



More information about the Python-list mailing list