list comprehension

Patrick Maupin pmaupin at gmail.com
Tue Jan 24 17:16:41 CET 2006


Duncan Booth wrote:

> I prefer writing an 'if' statement here, Bryan prefers 'get', that's just a
> choice of style. But 'setdefault' here, that has no style.

Well, I'm often told I have no style, and I _did_ admit that it's an
abuse of setdefault.  However, I often use setdefault to populate
nested dictionaries, or dictionaries of sets or lists, e.g.:

for x, y in somebiglist:
    bigdict.setdefault(x,set()).add(y)   # Strips duplicates


for x, y in somebiglist:
    bigdict.setdefault(x,[]).append(y)   # Preserves duplicates

To my mind, this latter is so much cleaner and clearer than any of the
alternatives that it just isn't funny:

for x, y in somebiglist:
    if x in bigdict:
        bigdict[x].append(y)
    else:
        bigdict[x] = [y]

for x, y in somebiglist:
    if x not in bigdict:
        bigdict[x] = []
    bigdict[x].append(y)

for x, y in somebiglist:
    try:
        bigdict[x].append(y)
    except KeyError:
        bigdict[x] = [y]

etc.

Since I use setdefault in this manner quite often, I am very
comfortable with it.  On a single line I know what I am creating (list,
dict, set, etc.), what the default value is, and how it is being
modified.

Because I am NOT a believer in the Perl idiom of TMTOWTDI, and because,
TO ME, setdefault screams "This line is creating and subsequently
modifying a dictionary entry", setdefault is absolutely my first choice
for this particular task.

Having said that, my enthusiasm for setdefault (for the given problem!)
IS tempered somewhat by having to abuse a list as a mutable integer.
That is the only reason that I concede that my solution is an abuse of
setdefault, but the setdefault idiom is (to me) so clear and compelling
that I view it as a toss-up whether to use a single line setdefault or
an if/else in this case.

And, as I mentioned earlier, if I had to do this same thing LOTS of
times in a program, I most likely would code a class (perhaps not as
fancy as a true mutable int, but certainly something with an increment
method), because, IMO, it would be a lot cleaner (hmmm, maybe there's
no style points in that) than tons and tons of if/else statements.

Regards,
Pat




More information about the Python-list mailing list