Optional parameter object re-used when instantiating multiple objects

George Sakkis george.sakkis at gmail.com
Sun Nov 16 04:10:14 EST 2008


On Nov 16, 2:05 am, Arnaud Delobelle <arno... at googlemail.com> wrote:

> Steven D'Aprano <st... at REMOVE-THIS-cybersource.com.au> writes:
> > On Sat, 15 Nov 2008 01:40:04 -0800, Rick Giuly wrote:
>
> >> Hello All,
>
> >> Why is python designed so that b and c (according to code below)
> >> actually share the same list object? It seems more natural to me that
> >> each object would be created with a new list object in the points
> >> variable.
>
> > That's not natural *at all*. You're initialising the argument "points"
> > with the same list every time. If you wanted it to have a different list
> > each time, you should have said so. Don't blame the language for doing
> > exactly what you told it to do.
>
> Come on.  The fact that this questions comes up so often (twice in 24h)
> is proof that this is a surprising behaviour.  I do think it is the
> correct one but it is very natural to assume that when you write
>
>     def foo(bar=[]):
>          bar.append(6)
>          ...
>
> you are describing what happens when you _call_ foo, i.e.:
>
>     1. if bar is not provided, make it equal to []
>     2. Append 6 to bar
>     3. ...

+1. Understanding and accepting the current behavior (mainly because
of the extra performance penalty of evaluating the default expressions
on every call would incur) is one thing, claiming that it is somehow
natural is plain silly, as dozens of threads keep showing time and
time again. For better or for worse the current semantics will
probably stay forever but I wish Python grows at least a syntax to
make the expected semantics easier to express, something like:

def foo(bar=`[]`):
    bar.append(6)

where `expr` would mean "evaluate the expression in the function
body". Apart from the obvious usage for mutable objects, an added
benefit would be to have default arguments that depend on previous
arguments:

def foo(x, y=`x*x`, z=`x+y`):
    return x+y+z

as opposed to the more verbose and less obvious current hack:

def foo(x, y=None, z=None):
    if y is None: y = x*x
    if z is None: z = x+y
    return x+y+z

George



More information about the Python-list mailing list