[Tutor] Prevent "Coder's Remorse"?

Kent Johnson kent37 at tds.net
Thu Sep 29 11:49:42 CEST 2005


Kent Johnson wrote:

> I'm curious about why you want to do this, it is kind of a strange
> requirement. But anyway, here is a class that subclasses dict and
> presents the interface you want to client code. It doesn't actually
> update all instances when you add or delete a key; it keeps a list of
> valid keys in a class attribute and updates this list when you add or
> delete. Then when you access a key it checks the list of valid keys.
> If the key you want is not in the list, you get a KeyError - the
> instance dict is never checked. If the key you want is in the list
> but not in the instance, you get the default value.

This class needs a little more work to correctly model a dictionary - its keys(), values(), items(), __contains__(), __iter__() and iteritems() methods at least need customization to work from the _keys attribute. One way to do this would be to inherit from UserDict.DictMixin; then only keys() would have to be defined.

Kent
 
> I don't see any need to actually add default values to all the dicts.
> Conceivably to save memory you might want to actually delete values
> from all the dicts; to do this you could keep a list of all the
> existing dicts as another class attribute. I'm not sure you will save
> much though as the dict itself probably doesn't resize downward. A
> side effect of not deleting keys is that if you delete and then
> restore a key, instances that had that key before will magically
> restore their old value. This could be a bug or a feature depending
> on your requirements.
> 
> Finally, the set of valid keys is shared by all instances, so if you
> want to use this for two different types of things you will have to
> make subclasses and give each subclass its own _key attribute.> 
> Requires Python 2.3 or greater
> 
> Kent
> 
> # CommonKeysDict.py
> # Make it work with Python 2.3
> try:
>     set
> except NameError:
>     from sets import Set as set
>     
> class CommonKeysDict(dict):
>     """Dictionary where all instances must have the same set of keys
>        and with a default value for unknown keys.
>        
>        >>> d = CommonKeysDict()
>        >>> d[0]
>        Traceback (most recent call last):
>          ...
>        KeyError: 0
>        
>        >>> d[0] = 1
>        >>> d[0]
>        1
>        
>        A second instance will get the default value for keys that are in use:
>        >>> d2 = CommonKeysDict()
>        >>> d2[0]
>        'default'
>        
>        The second instance can have its own values
>        >>> d2[0] = 2
>        >>> d2[0]
>        2
>        >>> d[0]
>        1
>        
>        Deleting a key from any instance removes that key from the allowed set.
>        Note that this doesn't actually delete the key from all instances, it just
>        makes it inaccessible.
>        
>        >>> del d[0]
>        >>> d2[0]
>        Traceback (most recent call last):
>          ...
>        KeyError: 0
>        
>     """
>     
>     _keys = set()
>     
>     def __init__(self, **items):
>         dict.__init__(self, **items)
> 
>     def __getitem__(self, key):
>         if key not in self._keys:
>             raise KeyError, key
>         try: 
>             return dict.__getitem__(self, key)
>         except KeyError:
>             return 'default'
> 
> 
>     def __setitem__(self, key, value):
>         self._keys.add(key)
>         dict.__setitem__(self, key, value)
>     
>     
>     def __delitem__(self, key):
>         self._keys.remove(key)
>         dict.__delitem__(self, key)
>         
>         
> def _test():
>     import doctest
>     doctest.testmod()
> 
> if __name__ == "__main__":
>     _test()
> 
> 
> _______________________________________________
> Tutor maillist  -  Tutor at python.org
> http://mail.python.org/mailman/listinfo/tutor
> 
> 



More information about the Tutor mailing list