Changing argument value

Tim Roberts timr at probo.com
Sat Dec 15 03:10:42 EST 2007


Stargaming <stargaming at gmail.com> wrote:
>
>Even though you have the assignment operator *in both cases*, it does 
>**not** issue the same thing. 
>
>As Bruno pointed out, in the first case ``y = [3,4]`` it is *rebinding* 
>the name `y`.

There have been two good replies to this, but I would like to present the
"mental model" I use to understand this.  The term "rebinding" is not one
that folks encounter very often, and so doesn't bring up an image.

In Python, you have objects (which do not have names), and you have names.
Names get "bound" to objects.  For example:

  x = [1,2,3]

This statement creates an anonymous object out in space.  The object is a
list, containing three numbers.  It also creates a name "x" in a namespace,
and binds it to that anonymous list.

Now, let's say I do this:

  x = [1,2,6]

This creates a NEW anonymous object out in space -- a list containing three
numbers -- and binds the name "x" to it.  For a short time, we now have TWO
three-element lists in our object space.  The old list ([1,2,3]) now has
nothing bound to it, so it will eventually be cleaned up by the garbage
collector.  x is now bound to an entirely different object.

But, if I did this INSTEAD of that:

  x[2] = 6

This does NOT create a new list.  Instead, it changes one element in that
first anonymous list object we created.  x is still bound to that same
list.

So, consider your example:

    def fooA(y):
	y = [3,4]
	return y

    def fooB(y):
	y[0] = 3
	y[1] = 4
	return y

   x = [1,2]
   fooA(x)

"x" is just a name in the global namespace.  We don't really pass "x" to
the function.  Instead, we pass that anonymous list object with
two-elements.  As the function is called, that list gets bound to the name
"y" inside fooA.  This list now has TWO names bound to it, "x" in the
global namespace, and "y" in the fooA function.

When you execute 
    y = [3,4]
you are creating a brand-new list with two elements, and bunding that to
the local name "y".  The old list STILL EXISTS, and since it is still bound
to the global "x", it won't be cleaned up.  When the function returns, the
name "y" goes away, so it gets unbound.  Since you don't store the function
result anywhere, the [3,4] list now has no names bound to it, and will get
cleaned up.

    fooB(x)

Like before, this is passing the two-element [1,2] list into fooB, where it
gets bound to "y" inside fooB.  Again, it has two names bound to it.  Then,
when you do
    y[0] = 3
you are changing an element in that list.  Since that same list is bound to
both the global "x" and the local "y", the effect of the changes WILL be
seen when you exit from function.
-- 
Tim Roberts, timr at probo.com
Providenza & Boekelheide, Inc.



More information about the Python-list mailing list