Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #90622 > unrolled thread

a python pitfall

Started byBilly Earney <billy.earney@gmail.com>
First post2015-05-14 13:06 -0500
Last post2015-05-15 12:03 +1000
Articles 2 — 2 participants

Back to article view | Back to comp.lang.python


Contents

  a python pitfall Billy Earney <billy.earney@gmail.com> - 2015-05-14 13:06 -0500
    Re: a python pitfall Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-05-15 12:03 +1000

#90622 — a python pitfall

FromBilly Earney <billy.earney@gmail.com>
Date2015-05-14 13:06 -0500
Subjecta python pitfall
Message-ID<mailman.11.1431626772.17265.python-list@python.org>

[Multipart message — attachments visible in raw view] — view raw

Hello friends:

I saw the following example at
http://nafiulis.me/potential-pythonic-pitfalls.html#using-mutable-default-arguments
and
did not believe the output produced and had to try it for myself....

def foo(a,b,c=[]):
    c.append(a)
    c.append(b)
    print(c)

foo(1,1)
foo(1,1)
foo(1,1)

produces:
[1, 1]
[1, 1, 1, 1]
[1, 1, 1, 1, 1, 1]

One would expect the following output:
[1, 1]
[1, 1]
[1, 1]

Doesn't this valid the zen of python: "Explicit is better than implicit."  ?

Thanks!
Billy

[toc] | [next] | [standalone]


#90638

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-05-15 12:03 +1000
Message-ID<555553db$0$12985$c3e8da3$5496439d@news.astraweb.com>
In reply to#90622
On Fri, 15 May 2015 04:06 am, Billy Earney wrote:

> Hello friends:
> 
> I saw the following example at
>
http://nafiulis.me/potential-pythonic-pitfalls.html#using-mutable-default-arguments
> and
> did not believe the output produced and had to try it for myself....
> 
> def foo(a,b,c=[]):
>     c.append(a)
>     c.append(b)
>     print(c)
> 
> foo(1,1)
> foo(1,1)
> foo(1,1)
> 
> produces:
> [1, 1]
> [1, 1, 1, 1]
> [1, 1, 1, 1, 1, 1]
> 
> One would expect the following output:
> [1, 1]
> [1, 1]
> [1, 1]

Really? Why would you expect that?

The *body* of the function is executed every time the function runs. The
*definition* of the function is executed once, and only once, when the
function is first defined. Setting the default value of a parameter is part
of the definition, not the body, and so it happens once only, not every
time. It truly would be surprising if the function recalculated the default
value every time.

Since the default value for c is a list, you are mutating the *same list*
each time.

This question comes up repeatedly. It's a FAQ, and the most recent time was
less than a week ago:

https://mail.python.org/pipermail/python-list/2015-May/703043.html

See, in particular, my response:

https://mail.python.org/pipermail/python-list/2015-May/703065.html


> Doesn't this valid the zen of python: "Explicit is better than implicit." 
> ?

I think you mean "invalidate".

No, this has nothing to do with explicitness or implicitness. Regardless of
whether Python uses "early binding" or "late binding" of the default
parameter, it is still equally explicit. The problem occurs because people
assume one binding model (which is entirely inconsistent with everything
else in Python) and get it wrong: people assume that function defaults are
late binding, but they are not.


-- 
Steven

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web