A small proposed change to dictionaries' "get" method

Alex Martelli alex at magenta.com
Thu Aug 3 05:08:21 EDT 2000


"Gareth McCaughan" <Gareth.McCaughan at pobox.com> wrote in message
news:slrn8oh81f.1m8e.Gareth.McCaughan at g.local...
    [snip]
>         existing_lines = word2lines.get(word, [])   |
>         existing_lines.append(line_number)          | ugh!
>         word2lines[word] = existing_lines           |
    [snip]
> All very simple and elegant. There's just one wart: the
> three lines I've labelled "ugh!" seem much more verbose
> and inefficient than they should be. We have to search
> word2lines twice for "word" (once to see if it's there,

Agreed. As a stylistic issue, I'd probably code it as:
            try:
                word2lines[word].append(line_number)
            except KeyError:
                word2lines[word]=[line_number]
Yeah, I know, that's 4 lines instead of 3:-).  But it looks
more natural to me -- the mainstream being to append
one more line number, the exceptional case to create
a new list with just the current line-number in it.  Eye of
the beholder, no doubt.

> This (update a mutable object that's a value in a dictionary,
> initialising it first if appropriate) is a common idiom, at
> least in my programs. It's a shame that it should be so ugly.

Yes, I use it often, too.  Good point.


> I suggest a minor change: another optional argument to
> "get" so that
>
>     dict.get(item,default,flag)
>
> is equivalent to
>
>     if dict.has_key(item):
>       VALUE IS dict[item]
>     else:
>       if flag: dict[item] = default    <-- This is all that's new
>       VALUE IS default

Nice, except I wouldn't call it 'get' and distinguish it from the
normal case with an extra optional flag, but rather give it
another name (hard to find a good one without more thought,
but it should give a hint that it can mutate the dict; maybe
mutatingGet, but that seems far too verbose...).

Of course, it doesn't really have to be a member of dict
(of course you can make it one through UserDict):

def myget(dict, item, default):
    if not dict.has_key(item):
        dict[item]=default
    return dict[item]


I realize that calling myget(dict,item,default) is not as
syntactically neat as calling dict.myget(item,default),
but it's not really too bad, is it?  Of course, having it as
a member would likely be slightly more efficient as
well as syntactically neater.  And I do believe the need
is widespread enough -- maybe as high as for the non
mutating variant of get we now have.  C++ automagically
adds keys to a std::map when they're referred to through
operator[], and, just for once, it may be more convenient
than Python in this one regard!-)


Alex






More information about the Python-list mailing list