dict.get(key, default) evaluates default even if key exists

Dan Stromberg drsalists at gmail.com
Tue Dec 15 16:10:42 EST 2020


On Tue, Dec 15, 2020 at 11:05 AM Serhiy Storchaka <storchaka at gmail.com>
wrote:

> 15.12.20 19:07, Mark Polesky via Python-list пише:
> > # Running this script....
> >
> > D = {'a':1}
> > def get_default():
> >     print('Nobody expects this')
> >     return 0
> > print(D.get('a', get_default()))
> >
> > # ...generates this output:
> >
> > Nobody expects this
> > 1
> >
> > ###
> >
> > Since I'm brand new to this community, I thought I'd ask here first...
> Is this worthy of a bug report?  This behavior is definitely unexpected to
> me, and I accidentally coded an endless loop in a mutual recursion
> situation because of it.  Calling dict.get.__doc__ only gives this short
> sentence: Return the value for key if key is in the dictionary, else
> default.  Nothing in that docstring suggests that the default value is
> evaluated even if the key exists, and I can't think of any good reason to
> do so.
> >
> > Am I missing something?
>
> You are missed that expressions for function arguments are always
> evaluated before passing their values to a function. This is expected
> behavior, and I can't remember any programming language in which it's
> different.
>
I think Haskell might be different. It's a lazy language. So its '&&' and
'||' operators aren't specialcased by the language implementation to be
short-circuit - everything is just lazy naturally.  It's a neat idea, but
it's kind of hard to reason about its performance characteristics.  Python
has laziness in its 'and' and 'or', as well as in its generators - this
gives laziness where you tend to need it the most, without Python's
performance becoming hard to reason about (modulo the garbage collector).

One of the coolest things about Haskell is if you write a sort function in
it, then you can get a "give me the n lowest values" function for free.
That's lazy.


More information about the Python-list mailing list