[Tutor] Confused about functions

Lloyd Kvam lkvam@venix.com
Thu, 01 Nov 2001 19:10:21 -0500


Here's my mental image (for better or worse).

X = 1
Python creates a "bucket of bits" where the bits represent a one.  Then 
Python writes an X on a sticky label.  Finaly the label is stuck on the 
bucket.

In C (or VB or COBOL or Fortran ...)
X = 1
C takes the bits that represent 1 and sticks them in a bucket labeled X. 
  The programmer must have created that bucket by declaring X.  (int X;, 
or  DIM X AS Integer, etc.)

L = [1,2]
Python again creates a "bucket of bits" and sticks in bits for a one and 
a two.  A sticky label of L is attached.  This bucket is different.  It 
is mutable.  You can change the bits in the bucket.

L[0] = 3
Python finds the bucket with the L label, takes out the bits at the zero 
postion and replaces them with bits that represent three.

X = 3
Python creates a new bit bucket with bits representing three in the 
bucket.  Then it finds the X label, peels it off the old bucket and 
sticks it on the new bucket.  If the old bucket has no labels it is 
recycled (garbage collection).

Y = X
Python finds the Y label (or creates a new label for Y) and then sticks 
it on the bucket that already has an X label.  Buckets can have many labels.


I hope that helps.  While Python programs do not necessarily look so 
very different from C or Java programs, the underlying variable handling 
is different.  For most situations, Python's immutable "buckets" are a 
big improvement.

Titu Kim wrote:

> So, can i conclude that in local namespace of
> changer(), object reference of 'x' is altered to point
> to integer 1, while object reference of 'X' in global
> namespace still points to integer 2? If i define my
> changer as 'changer(X,Y)', changer() still behaves the
> same way because 'X' in changer() and 'X' in global
> reside at different momory location(although same
> name) but they point to same memory location of
> integer '2'. Once i changer laters object reference of
> local 'X' to point to integer '1', then at this point
> two 'X's refer to different memory locations. Am
> thinking in right direction? Please correct me.
> 
> Regards,
> Kim Titu.
> --- Andrew Wilkins <toodles@yifan.net> wrote:
> 
>>>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
>>>>>
>>>>>
>>>>>
> === message truncated ===
> 
> 
> __________________________________________________
> 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
> 
> 


-- 
Lloyd Kvam
Venix Corp.
1 Court Street, Suite 378
Lebanon, NH 03766-1358

voice: 
603-443-6155
fax: 
801-459-9582