Some strange behaviours of default arguments

Thomas Wouters thomas at xs4all.net
Tue Oct 31 14:37:06 EST 2000


On Wed, Nov 01, 2000 at 04:14:23AM +0900, June Kim wrote:

> def add(a, list=[]):
>     list.append(a)
>     print list

> (I think "list" is a local variable, and every time the function
> is called without the optional argument, the variable is initiated
> with a new object, blank list -- but Python 2.0 doesn't work that way)

Nor does Python 1.5.2. 'list' is a local variable, but it's also an argument
with a default value. That default is stored in the code object, not just
the local namespace, and the reference is copied to the local (to that
function) namespace when you don't supply a value for it.

That means that if the default value is mutable, like lists, you get a
'static' variable that retains its value over calls. If you supply a value,
that value will be used for 'list', but *not* stored back in the code
object. So, after this:

> >>> add(3)
> [3]
> >>> add(5)
> [3,5]

This should happen:

>>> add(5,[20,10])
[20, 10, 5]
>>> add(7)
[3, 5, 7]

> Why is the local variable "list"  NOT initialized with the default
> value every time I call it? Can anyone gimme some, if any,
> reasonable explanation?

It's not meant to be initialized :) Contrary to the Perl 'static' variables,
which happened by accident, this was designed this way. It's listed in the
docs and in the FAQ, too.

Aint-Python-great-ly y'rs,


(Horribly off-topic, but amusing: Perl static variables are really funny,
but only because they 'evolved' into the language without anyone noticing it
;) Perl has two kinds of 'if' constructs (not counting the reverse-if alias
of 'unless'):

if (condition) { /* code */ }

and

/* code */ if (condition);

The main difference between the two is that the 'normal' if starts a block,
and thus a lexical closure. The 'short' if doesn't do that, all the
conditionally evaluated code is in the same scope as the enclosing code. So
if you do 

if (1) { my $var = 1; /* use $var somehow */ }

the variable $var is automatically deallocated at the end of the block, and
isn't available to code following the if(). But if you do 

my $var if (1);

the variable is actually created in the local scope (an entry in the symbol
table is added, so to speak, so it's visible to everyone in the same and
enclosed scopes) but the code to set the value on code-block-entry
and clear the value again on code-block-exit isn't generated unless the
condition is true. So if you set the value somewhere in your code (outside
the 'if' construct) it won't get wiped when you exit the code block, and
when you re-enter it, the variable will have kept its value. And it was a
suprise to everyone that it worked, apparently, because it wasn't designed
that way ;))

-- 
Thomas Wouters <thomas at xs4all.net>

Hi! I'm a .signature virus! copy me into your .signature file to help me spread!




More information about the Python-list mailing list