[Python-Dev] Proposal: defaultdict

Ian Bicking ianb at colorstudy.com
Sat Feb 18 01:32:23 CET 2006

Martin v. Löwis wrote:
> Adam Olsen wrote:
>>Consider these two pieces of code:
>>if key in d:
>>  dosomething(d[key])
>>  dosomethingelse()
>>  dosomething(d[key])
>>except KeyError:
>>  dosomethingelse()
>>Before they were the same (assuming dosomething() won't raise
>>KeyError).  Now they would behave differently.
> I personally think they should continue to do the same thing,
> i.e. "in" should return True if there is a default; in the
> current proposal, it should invoke the default factory.

As I believe Fredrik implied, this would break the symmetry between "x 
in d" and "x in d.keys()" (unless d.keys() enumerates all possible 
keys), and either .get() would become useless, or it would also act in 
inconsistent ways.  I think these broken expectations are much worse 
than what Adam's talking about.

> But that's beside the point: Where is the real example
> where this difference would matter? (I'm not asking for
> a realistic example, I'm asking for a real one)

Well, here's a kind of an example: WSGI specifies that the environment 
must be a dictionary, and nothing but a dictionary.  I think it would 
have to be updated to say that it must be a dictionary with 
default_factory not set, as default_factory would break the 
predictability that was the reason WSGI specified exactly a dictionary 
(and not a dictionary-like object or subclass).  So there's something 
that becomes brokenish.

I think this is the primary kind of breakage -- dictionaries with 
default_factory set are not acceptable objects when a "plain" dictionary 
is expected.  Of course, it can always be claimed that it's the fault of 
the person who passes in such a dictionary (they could have passed in 
None and it would probably also be broken).  But now all of the sudden I 
have to say "x(a) takes a dictionary argument.  Oh, and don't you dare 
use the default_factory feature!" where before I could just say 
"dictionary".  And KeyError just... disappears.  KeyError is one of 
those errors that you *expect* to happen (maybe the "Error" part is a 
misnomer); having it disappear is a major change.

Also, I believe there's two ways to handle thread safety, both of which 
are broken:

1) d[key] gets the GIL, and thus while default_factory is being called 
the GIL is locked

2) d[key] doesn't get the GIL and so d[key].append(1) may not actually 
lead to 1 being in d[key] if another thread is appending something to 
the same key at the same time, and the key is not yet present in d.

Admittedly I don't understand the ins and outs of the GIL, so the first 
case might not actually need to acquire the GIL.

Ian Bicking  /  ianb at colorstudy.com  /  http://blog.ianbicking.org

More information about the Python-Dev mailing list