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) -- http://mail.python.org/mailman/listinfo/python-list