[Python-3000] A request to keep dict.setdefault() in 3.0
Phillip J. Eby
pje at telecommunity.com
Mon Jul 9 20:44:09 CEST 2007
PEP 3100 suggests dict.setdefault() may be removed in Python 3, since
it is in principle no longer necessary (due to the new defaultdict type).
However, there is another class of use cases which use setdefault for
its limited atomic properties - the initialization of non-mutated
data structures that are shared among threads. (And defaultdict
cannot achieve the same thing.)
I currently have three places where I use this, off the top of my head:
1. a "synchronized" decorator that initializes an object's __lock__
attribute (if not found) using ob.__dict__.setdefault('__lock__',
allocate_lock())
2. an Aspect implementation that does almost exactly the same thing,
so that if multiple threads ask for an Aspect that doesn't exist for
a given object, they will not end up using different instances.
3. a configuration library that supports "write many, read once"
configurations shared across threads. A key may have its value
written to any number of times, so long as it has never been
read. As soon as the value has been read by any thread, it becomes
fixed and it cannot be set to any other value. (Setting it to the
same value has no effect.) This is essentially a simple way of
having a provably race-condition-free data structure -- if you have a
race condition, you will get an error. As a bonus, it is completely
non-blocking and single threaded code does not pay any overhead for
the use of the data structures.
Of course, to take advantage of setdefault's atomic properties, one
must be using CPython, and all the dictionary keys must have __hash__
and __eq__ methods implemented entirely in C (recursively to their
contents, if tuples are involved). However, for all three of the
above applications this latter condition is actually quite trivial to ensure.
I realize, however, that this is an "impure" usage, in that other
Python implementations usually do not have any atomicity guarantees,
period. But it would save me having to write a setdefault function
in C when porting any of the above code to 3.0. ;-)
More information about the Python-3000
mailing list