[Tutor] Function Return Values (or References)

Dave Angel davea at davea.name
Mon Jun 24 11:54:35 CEST 2013


On 06/24/2013 04:12 AM, John Steedman wrote:
> Hi Tutors,
>
> I'm confused by the following possible contradiction. Would someone please
> explain or point me to the right docs.
>
> FACT 1
>
> "Variables in python hold references to objects."
> http://en.wikipedia.org/wiki/Python_syntax_and_semantics
>
> FACT 2
>
>>>> def Increment ( x ) :
>>>>     // return x + 1
>>>>     x = x + 1
>>>>     return x
>>>>
>>>> y = 1
>>>> z = Increment ( y )
>>>> y
> 1
>>>> z
> 2
>
> By FACT 1  x should be a reference parameter...?
> By Fact 2 x would seem to be a copy...?
>
> What in the world of dynamic typing is going on?
>

Python docs usually use the word "binding" rather than reference.  A 
variable (name) is bound to an object.  But it can be rebound.  For 
example, any assignment rebinds the name to a (possibly new) object.  So 
as soon as you did the x=x+1, you're no longer referring to the original 
object.

Another factor is that int (and float, str, and tuple, plus some others) 
is immutable.  That means that once the object is created, its value 
cannot change.  So there's no way to change the Increment() function to 
do exactly what you ask for.  Since y is bound to an immutable object, 
the function cannot change that value.

Now let's choose a mutable object and try the analogous thing.

def add_to_end(mylist):
     mylist = mylist + [42]
     return mylist

Once again, if we test it with
k = [4]
j = add_to_end(k)
k
j

we'll see that k is unchanged.  But this one we CAN fix.

def add_to_end(mylist):
     mylist.append(42)
     #notice we do NOT rebind it, we mutate the object inplace
     return mylist

Incidentally, convention is that if a function mutates its (single) 
argument, it does not return it, and if it returns a modified copy, it 
doesn't alter the original.  See for example sort() and sorted(), 
respectively.

If you happen to be familiar with C++, a reference there is bound once 
when it's defined, and it cannot be changed to reference a different 
object.  What would be equivalent to a python rebinding is simply a 
compile-time error.  Of course in C++, whenever such things get in the 
way, you fake your way out with casting.

Hope this helps.


-- 
DaveA


More information about the Tutor mailing list