[Tutor] Confused about functions

Andrew Wilkins toodles@yifan.net
Fri, 2 Nov 2001 02:34:10 +0800


> I am making these statement without refering to the
> source. If i am wrong, please correct me.
>     To explain the behaviour in changer(), i believe
> python by default passes changer a copy of x, but an
> object reference to the list L. Thus, changer makes
> change on the copy of x but changes the original list
> L.

In section 4.6 Defining Functions of the Python tutorial:
"The actual parameters (arguments) to a function call are introduced in the
local symbol table of the called function when it is called; thus, arguments
are passed using call by value (where the value is always an object
reference, not the value of the object)."

The objects are both passed in by reference. The difference is (as Remco,
Kalle and Andrei pointed out) in the use of the assignment operator and the
fact that "x" refers to a name and y[0] refers directly to an object.

In the case of
    x=1
the integer 1 is given an alias of "x", but only in the local namespace.
Think of it this way: "X" is in the global namespace, referring to the
integer 2. When X is passed to changer, a reference is created and bound to
the alias "x" in the local namespace. When "x=1" is evaluated, rather than
assigning 1 to the value of "x" it is rebinds "x" to refer to the integer 1.
Given that the object reference was changed and the value of the object "x"
was originally referring to wasn't changed, the value of "X" will remain the
same in the global namespace.

In the case of
    y[0]='spam'
because y[0] is not a name but an object, the value of object that y and Y
will change.

ERGH that sounds really bad I hope you can understand me...

Regards,
Andrew

> --- Andrei Kulakov <sill@optonline.net> wrote:
> > On Thu, Nov 01, 2001 at 02:08:51AM -0600, Kit
> > O'Connell wrote:
> > > I am working my way through Learning Python (from
> > O'Reilly). I am reading
> > > about functions and how they interact with
> > variables (on built-in, global,
> > > and local levels). The following example code is
> > given:
> > >
> > > def changer (x,y):
> > > x = 2
> > > y[0] = 'spam'
> > >
> > > X = 1
> > > L = [1, 2]
> > > changer (X, L)
> > >
> > > at the end of the code, the value of X remains 1,
> > because x is only set to
> > > 2 on a local level within the function. However, L
> > has chaned to ['spam',
> > > 2].
> > >
> > > I am confused. Why does L change, but X doesn't? I
> > hope someone can
> > > explain this for me a bit.
> >
> > Consider this:
> >
> > def changer(x, y):
> >     x = 1
> >     y = [1,2]
> >
> > X = 2
> > Y = [3,4]
> > changer(X, Y)
> > print X, Y # prints 2, [3,4]
> >
> > Parts of lists can be changed, on the fly. In your
> > code, that's precisely
> > what you do. Lists can often be quite large
> > (millions of items) and you
> > often want to change just one item (or a few) of
> > that list, instead of
> > making a copy. Imagine how much more expensive it'd
> > be to make a new copy
> > of a million-item list and change stuff in the new
> > copy, and keep the old
> > one unchanged!
> >
> > Now you're probably thinking, well, why doesn't the
> > integer here behave
> > consistently with a list, then? The reason is
> > encapsulation of data -
> > in a solid program, you want to pass some stuff into
> > a function and get
> > results. For instance:
> >
> > def mult(x, y):
> >   return x * y
> >
> > Now, if you're thinking at the place in the code
> > where you call this
> > function, you'll see this:
> >
> > result = mult(val1, val2)
> >
> > You shouldn't need to look at the function to be
> > sure that val1 and val2
> > don't change. If mult changed val1, for instance,
> > that'd be bad because
> > when you look at the line above, it looks like you
> > just pass two values
> > in and get a result. This makes for a much more
> > clearer program: if you
> > look through code and try to figure out the flow of
> > logic, you don't have
> > to constantly jump to that functions code to check
> > whether it modified
> > a variable or not.
> >
> > These behaviours are only the reasonable defaults,
> > you can override both.
> >
> > This would change X outside the function:
> >
> > def changer(x, y):
> >   global X
> >   X = 1
> >
> > This would keep Y list unchanged:
> >
> > def changer(x, y):
> >   z = y[:]  # make a copy of y list
> >   z[0] = "spam"
> >
> > But, you know, I'm not sure what I said here is
> > exactly right.. if you know
> > otherwise, please correct me!
> >
> >
> > >
> > > Also, does anyone have an opinion on the Python
> > Essential Referance from
> > > New Riders? How does it compare to O'Reilly's
> > Programming Python or their
> > > Standard Library book?
> > >
> > > Thanks!
> > > Kit
> > >
> > > --
> > >  * Bring to me a handful of stardust,  *    Kit
> > O'Connell
> > > * that I can cast into my darkest night *
> > vulpine@pobox.com
> > >  * -Dream Trybe, "Come Down"      *
> > http://www.dreamspeakers.net/
> > > *       http://www.dreamtrybe.com/      *
> > Austin, Texas, Planet Earth
> > > 'finger vulpine@io.com' for PGP key
> > >
> > >
> > > _______________________________________________
> > > Tutor maillist  -  Tutor@python.org
> > > http://mail.python.org/mailman/listinfo/tutor
> >
> > --
> > Cymbaline: intelligent learning mp3 player - python,
> > linux, console.
> > get it at: cy.silmarill.org
> >
> > _______________________________________________
> > Tutor maillist  -  Tutor@python.org
> > http://mail.python.org/mailman/listinfo/tutor
>
>
> __________________________________________________
> Do You Yahoo!?
> Make a great connection at Yahoo! Personals.
> http://personals.yahoo.com
>
> _______________________________________________
> Tutor maillist  -  Tutor@python.org
> http://mail.python.org/mailman/listinfo/tutor
>