a python pitfall

Steven D'Aprano steve+comp.lang.python at pearwood.info
Thu May 14 22:03:06 EDT 2015


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




More information about the Python-list mailing list