[Python-Dev] Add a frozendict builtin type

Victor Stinner victor.stinner at haypocalc.com
Mon Feb 27 19:53:27 CET 2012


Rationale
=========

A frozendict type is a common request from users and there are various
implementations. There are two main Python implementations:

 * "blacklist": frozendict inheriting from dict and overriding methods
to raise an exception when trying to modify the frozendict
 * "whitelist": frozendict not inheriting from dict and only implement
some dict methods, or implement all dict methods but raise exceptions
when trying to modify the frozendict

The blacklist implementation has a major issue: it is still possible
to call write methods of the dict class (e.g. dict.set(my_frozendict,
key, value)).

The whitelist implementation has an issue: frozendict and dict are not
"compatible", dict is not a subclass of frozendict (and frozendict is
not a subclass of dict).

I propose to add a new frozendict builtin type and make dict type
inherits from it. frozendict would not have methods to modify its
content and values must be immutable.


Constraints
===========

 * frozendict values must be immutable, as dict keys
 * frozendict can be used with the C API of the dict object (e.g.
PyDict_GetItem) but write methods (e.g. PyDict_SetItem) would fail
with a TypeError ("expect dict, got frozendict")
 * frozendict.__hash__() has to be determinist
 * frozendict has not the following methods: clear, __delitem__, pop,
popitem, setdefault, __setitem__ and update. As tuple/frozenset has
less methods than list/set.
 * issubclass(dict, frozendict) is True, whereas
issubclass(frozendict, dict) is False


Implementation
==============

 * Add an hash field to the PyDictObject structure
 * Make dict inherits from frozendict
 * frozendict values are checked for immutability property by calling
their __hash__ method, with a fast-path for known immutable types
(int, float, bytes, str, tuple, frozenset)
 * frozendict.__hash__ computes hash(frozenset(self.items())) and
caches the result is its private hash attribute

Attached patch is a work-in-progress implementation.


TODO
====

 * Add a frozendict abstract base class to collections?
 * frozendict may not overallocate dictionary buckets?

--

Examples of frozendict implementations:

http://bob.pythonmac.org/archives/2005/03/04/frozendict/
http://code.activestate.com/recipes/498072-implementing-an-immutable-dictionary/
http://code.activestate.com/recipes/414283-frozen-dictionaries/
http://corebio.googlecode.com/svn/trunk/apidocs/corebio.utils.frozendict-class.html
http://code.google.com/p/lingospot/source/browse/trunk/frozendict/frozendict.py
http://cmssdt.cern.ch/SDT/doxygen/CMSSW_4_4_2/doc/html/d6/d2f/classfrozendict_1_1frozendict.html

See also the recent discussion on python-list:

http://mail.python.org/pipermail/python-list/2012-February/1287658.html

--

See also the PEP 351.

Victor
-------------- next part --------------
A non-text attachment was scrubbed...
Name: frozendict.patch
Type: text/x-patch
Size: 24014 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-dev/attachments/20120227/ff1984ed/attachment.bin>


More information about the Python-Dev mailing list