Default value for optional parameters unexpected behaviour?

M

Marc Aymerich

Hi,
I'm trying to define a function that has an optional parameter which
should be an empty list whenever it isn't given. However, it takes as
value the same value as the last time the function was executed. What
is the reason of this behaviour? How does python deal with default
values (i.e. when are they assigned/created)?

Thanks :)
.... foo.append(1)
.... print foo
....
a() [1]
a() [1, 1]
a() [1, 1, 1]
a() [1, 1, 1, 1]
a() [1, 1, 1, 1, 1]
a()
[1, 1, 1, 1, 1, 1]
 
C

Corey Richardson

Excerpts from Marc Aymerich's message of Sun Jun 26 14:28:30 -0400 2011:
Hi,
I'm trying to define a function that has an optional parameter which
should be an empty list whenever it isn't given. However, it takes as
value the same value as the last time the function was executed. What
is the reason of this behaviour? How does python deal with default
values (i.e. when are they assigned/created)?

Thanks :)

Really common mistake, I made it myself too. When Python evaluates the
function, it sees the default parameter of `foo' as the new object you
create with []. It keeps that object around. The proper idiom instead of
... foo.append(1)
... print foo
...

is

def a(foo=None):
if foo is None:
foo = []
foo.append(1)
print foo
--
Corey Richardson
"Those who deny freedom to others, deserve it not for themselves"
-- Abraham Lincoln

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.17 (GNU/Linux)

iQEcBAEBCAAGBQJOB3wgAAoJEAFAbo/KNFvpOcYH/jrb1pD5t88KfyMDB4Uu/Rwc
okXbnkppQaWv5yD6zGImVpQT07e8geHqfbWhVuu8EZFr4zwsXQPcLu8n4hTsltH6
KFpzdWEJnqdr1DkU26dJhKBGdLpaXil6WxqWA2dERPCvEYNetQnkjpxhLJMuSDq8
osfx9mMhLiNmM5AAcqi+8+lm7xhSmLTHBEgIT9GTnrpdbxEWOtDRGXdiEb0FQB6A
2yc1aMGSWJgcvBPKRCgU336pIe5/miN+e9UDiCHpc3RnKaodThS5QVJQCDI99BW4
czbWMPzQLaVMLDnYzpjJ7lJ5BibuB0SVrrXuLCzC7YpMa2/HpKXbp11k7AlOP5E=
=m0c1
-----END PGP SIGNATURE-----
 
S

Shashank Singh

Hi,
I'm trying to define a function that has an optional parameter which
should be an empty list whenever it isn't given. However, it takes as
value the same value as the last time the function was executed. What
is the reason of this behaviour? How does python deal with default
values (i.e. when are they assigned/created)?

This has been discussed before in this list, quite a few times
http://mail.python.org/pipermail/python-list/2010-March/1239044.html

A solution is to accept default value as None assign to [] by checking
for None inside the function

def f(a=None):
if a is None: a = []
 
N

Noah Hall

Hi,
I'm trying to define a function that has an optional parameter which
should be an empty list whenever it isn't given. However, it takes as
value the same value as the last time the function was executed. What
is the reason of this behaviour? How does python deal with default
values (i.e. when are they assigned/created)?

Thanks :)
...  foo.append(1)
...  print foo
...
a() [1]
a() [1, 1]
a() [1, 1, 1]
a() [1, 1, 1, 1]
a() [1, 1, 1, 1, 1]
a()
[1, 1, 1, 1, 1, 1]

Your problem arises because lists are mutable. Because foo (by
default, initially) points to a given list, every time the function is
called, it uses the same list that foo was first pointed to, if the
default argument value is taken.
The way to fix this is to instead do -

def a(foo=None):
if foo is None:
foo = []
 
T

Terry Reedy

Hi,
I'm trying to define a function that has an optional parameter which
should be an empty list whenever it isn't given. However, it takes as
value the same value as the last time the function was executed. What
is the reason of this behaviour? How does python deal with default
values (i.e. when are they assigned/created)?

Our fine Language Reference. Compound Statements chapter, Function
definitions section, says in bold type: "Default parameter values are
evaluated when the function definition is executed. ". I presume the
tutorial says this somewhere too. Read both, along with the first 5
chanpter of the Library reference.

If you want code executed when you call the function, put it in the body
that is executed when you call the function

def f(lst = None):
if lst is None:
lst = []
...
 
B

Benjamin Kaplan

Hi,
I'm trying to define a function that has an optional parameter which
should be an empty list whenever it isn't given. However, it takes as
value the same value as the last time the function was executed. What
is the reason of this behaviour? How does python deal with default
values (i.e. when are they assigned/created)?

Thanks :)

So the thing about Python is that you don't actually declare
functions. You create them. def is an executable statement that
creates a function object. Default arguments are part of the function
object, so they get evaluated when the function is created.
Traceback (most recent call last):
File said:
.... a.append(1)
....
foo.func_defaults ([],)
foo()
foo.func_defaults ([1],)
 
C

Corey Richardson

Excerpts from Thomas L. Shinnick's message of Sun Jun 26 14:53:21 -0400 2011:
See reference manual section 7.6 "Function definitions" under the
discussion subtitle "Default parameter values are evaluated when the
function definition is executed. "
http://docs.python.org/reference/compound_stmts.html#function-definitions

Yes, this is discussed in many places and many times, but why isn't
it in the Python FAQ? Amazing, yes?

Well, to be fair, I don't think most people actually read the FAQ.
The FAQ does say:

"Default arguments can be used to determine values once, at compile
time instead of at run time. This can only be done for functions or
objects which will not be changed during program execution..."

And he did modify the list during program execution. However this
isn't exactly forthright if you aren't looking for it / know what
you're reading. I don't think it should be spilled out in detail but
maybe a "there are some tricks involved with mutable default
arguments (for example a list). Refer to the language reference
(LINK) for more details" would be useful.

But I'm not really certain that would make much of a difference.
I'll Cc this to (e-mail address removed).
--
Corey Richardson
"Those who deny freedom to others, deserve it not for themselves"
-- Abraham Lincoln

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.17 (GNU/Linux)

iQEcBAEBCAAGBQJOB4dRAAoJEAFAbo/KNFvpOBkH/02mQjm7OTmIr+pRz4vWUYhW
dFPzS5OJdAyVPvF4NSAGrDCBD7D5QkYTOvow+jz5zZ/b9veXAArb//XAKC6EjzdO
GuzFoOCKo28YMQ611tLL02ZI/7moB69Ftc3K/zD4uSFOgEok0coOwrQyOti1hsgw
er7W72SLsoRSeFqoreoGy8yXTOFdRT8SROgAoocVAgmyfGWgjVu2+cQoP5cONps2
Clwcgf0cXfcFsfyCYbyk6ZOmBxH+jDRrrvGPwIH3BnJt/8ECLfKRJNsquw81D9ti
E5+yf7lkmZO+zRpEGzwmn0AEQoDah4U78pLuxOMlPvGZaympCAH+ubgfTHG0BYE=
=W9Uf
-----END PGP SIGNATURE-----
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top