The rap against "while True:" loops

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sun Oct 18 07:18:20 CEST 2009


On Sat, 17 Oct 2009 15:22:59 -0700, Paul Rubin wrote:

> Terry Reedy <tjreedy at udel.edu> writes:
>> >    d[key] += value
>> 
>> Yes, the motivation was to reduce 4 lines to 1 line for a common use
>> case, and not because of any sense of 'inappropriateness'.
> 
> Reducing 4 confusing lines to 1 clear one is almost always appropriate.

This is true, but there is nothing confusing about "Asking for 
forgiveness is better than asking for permission".

For the record, the four lines Paul implies are "confusing" are:

try:
    d[key] += value
except KeyError:
    d[key] = value

Paul, if that confuses you, perhaps you should consider a change of 
career. *wink*

On the other hand:

d = collections.defaultdict(int)
d[key] += value

is confusing, at least to me. I would expect the argument to defaultdict 
to be the value used as a default, not a callable. In other words, I 
would expect the above to try adding the type `int` to the integer 
`value` and fail, and wonder why it wasn't written as:

d = collections.defaultdict(0)
d[key] += value

Having thought about it, I can see why defaultdict is done that way, 
instead of this:

class MyDefaultDict(dict):
    def __init__(self, default=None):
        self._default = default
    def __getitem__(self, key):
        if key in self:
            return self[key]
        else:
            return self._default

And here's why this doesn't work too well:

>>> d = MyDefaultDict([])
>>> d['a'] = [1,2]
>>> d['b'] = [3,4,5]
>>> d
{'a': [1, 2], 'b': [3, 4, 5]}
>>> d['c'] += [6,7]
>>> d
{'a': [1, 2], 'c': [6, 7], 'b': [3, 4, 5]}

So far so good. But wait:

>>> d['d'] += [8]
>>> d
{'a': [1, 2], 'c': [6, 7, 8], 'b': [3, 4, 5], 'd': [6, 7, 8]}

Oops. So even though it's initially surprising and even confusing, the 
API for collections.defaultdict functionally more useful.



-- 
Steven



More information about the Python-list mailing list