"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