Roose wrote:

> I think someone mentioned that it might be a problem to add another
> piece of state to all dicts though.  I don't know enough about the
> internals to say anything about this.
> 
> setdefault gets around this by having you pass in the value every
> time, so it doesn't have to store it.  It's very similar, but somehow
> many times more awkward.
> 

Another option with no storage overhead which goes part way to reducing
the awkwardness would be to provide a decorator class accessible through
dict. The decorator class would take a value or function to be used as
the default, but apart from __getitem__ would simply forward all other
methods through to the underlying dictionary. 

That gives you the ability to have not one default value for a
dictionary, but many different ones: you just decorate the dictionary
anywhere you need a default and use the underlying dictionary everywhere
else. 

Some code which demonstrates the principle rather than the
implementation. dictDefaultValue could be imagined as
dict.defaultValue, dictDefaultValue(d, ...) could be 
d.defaultValue(...) although the actual name used needs work:

>>> class dictDefaultValue(object):
        def __init__(self, d, value=_marker, function=_marker):
            self.__d = d
            if value is _marker:
                if function is _marker:
                    raise TypeError, "expected either value or function 
argument"
                self.__dv = function
            else:
                def defaultValue():
                    return value
                self.__dv = defaultValue
                
        def __getattr__(self, name):
            return getattr(self.__d, name)
        
        def __getitem__(self, name):
            try:
                return self.__d[name]
            except KeyError:
                value = self.__dv()
                self.__d[name] = value
                return value
        
        def __setitem__(self, name, value):
            self.__d[name] = value

            
>>> d = {}
>>> accumulator = dictDefaultValue(d, 0)
>>> accumulator['a'] += 1
>>> aggregator = dictDefaultValue(d, function=list)
>>> aggregator['b'].append('hello')
>>> d
{'a': 1, 'b': ['hello']}
>>> 
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to