Learntofish's Blog

A blog about math, physics and computer science

Call by Object Reference (Call by Sharing)

Posted by Ed on January 9, 2012

In the following I want to talk about Call by Object Reference also known as Call by Sharing. I will use Python to illustrate the concept.

1. Strange behavior?

Let’s have a look at the following Python code:

def changeList1(x):
    x.append(41)

def changeList2(x):
    x = [41,42]

Save the code in a file callBySharing.py and run it in the Python-Shell (if you use IDLE press F5; if you use a terminal use python -i callBySharing.py). Type the following in the Python-Shell:

>>> myList = [1,2,3]
>>> changeList1(myList)
>>> print(myList)
[1, 2, 3, 41]

– In line 1 we define a list.
– In line 2 we passed the list to the function changeList1(). If you look at the definition of changeList1() you will recognize that it tries to append the value 41 to the list.
– In line 3 we print the list and see that the value 41 indeed is appended to the list.
– As the name of the function changeList1() suggests we have been successful in changing the list.

Now, continue in the Python-Shell:

>>> yourList = [5,6,7]
>>> changeList2(yourList)
>>> print(yourList)
[5, 6, 7]
>>>

– In line 1 we create a list.
– In line 2 we pass the list to the function changeList2(). If you look at the definition of changeList2() it seems that it tries to change the list to [41,42].
– In line 3 we print the list and see that it has not changed.

2. Analyzing the functions

So, why did changeList1() modify the list and changeList2() not? To understand this let’s write the functions in another way. We will introduce a refCopy variable that illustrates a copy procedure (which is not visible).

def changeList1b(ref):
    refCopy = ref
    refCopy.append(41)

def changeList2b(ref):
    refCopy = ref
    refCopy = [41,42]

Add the code to the file callBySharing.py and run it again in the Python-Shell. Then type the following in the Python-Shell:

>>> myList = [1,2,3]
>>> changeList1b(myList)
>>> print(myList)
[1, 2, 3, 41]
>>>
>>> yourList = [5,6,7]
>>> changeList2b(yourList)
>>> print(yourList)
[5, 6, 7]
>>>

– In line 01-04 we used changeList1b() and were successful in modifying the list.
– In line 06-09 we used changeList2b() and were not successful in modifying the list.
So, we have the same behaviour as before but the new functions make it easier to see what is going on.

Let’s analyze the function changeList1b() by having a look at its definition:
– In line 1 we define its name.
– In line 2 we define refCopy = ref. Keep in mind that a reference is just something that contains a memory address of an object. For example, in the figure below the value of ref is the address of the object [1,2,3]. The address could be 49838280. With refCopy = ref we copy the address 49838280 and assign it to refCopy. In the figure you can see the result: we now have two references pointing to the same object, namely [1,2,3]. This is also known as object sharing since both references, ref and refCopy, share the same object.
– In line 3 we write refCopy.append(41). This just means the following: On the right hand side we have the value 41 and try to append this value to the object that refCopy is pointing to. We know from the figure below that refCopy is pointing to the list [1,2,3], therefore 41 is appended.

Now, let’s analyze the function changeList2b() by having a look at its definition:
– In line 5 we define its name.
– In line 6 we write refCopy = ref, i.e. we copy the value of ref and assign it to refCopy. For example, the address of ref is 43857600 which is then assigned to refCopy.
– In line 7 we write refCopy = [41,42]. On the right hand side we create a new object [41,42]. With refCopy = [41,42] we tell refCopy to point to this new object, i.e. the value of refCopy is not 43857600 anymore (this is the crucial point!). The new value of refCopy is the address of the object [41,42] which is 43932368 (see figure below).
As you can see in the figure below, the reference yourList still points to [5,6,7].

We saw that the value of a reference (an address) is copied. This is known as call by object reference or call by sharing.

3. An exercise
Let’s write a third version of the function:

def changeList3(x):
    x+=[2012,2013]  # append two values to the list

Here, we try to append the values 2012 and 2013 to the list. Your task:
a) Pass a list to this function and find out whether the list is changed.
b) Create a drawing of the references and objects that shows what happens.

Solution:
a) Save the code for changeList3() in the file callBySharing.py. Then, type the following in the Python-Shell:

>>> myList = [1,2,3]
>>> changeList3(myList)
>>> print(myList)
[1, 2, 3, 2012, 2013]

Line 4 shows that the list is changed.

b) This is a drawing of the references and objects. The address is made up.
Note: Although there is no refCopy in the definition of changeList3() you can imagine that the computer uses this. It’s just not visible to us.

4. Immutable objects – Strings and Numbers
Let’s try to change a string in a similar manner as changeList3():

def changeString(x):
    x+='World!'     # try to append 'World!' to the string

Note how the code looks similar to changeList3().

Save this function in the file callBySharing.py and run it in the Python-Shell. Then type the following in the Python-Shell:

>>> myString = 'Hello'
>>> changeString(myString)
>>> print(myString)
Hello

– In line 1 we created a reference myString to the object ‘Hello’.
– In line 2 we pass myString to the function changeString(). From the definition of the function changeString() we hope that ‘World’ is appended.
– In line 3 we print myString but we see in line 4 that ‘World’ is not appended.

Although we did the same thing as in changeList3() we still couldn’t change the object ‘Hello’. The reason is that strings are immutable objects, i.e. you can’t change the object.

——

In Python everything is an object, even simple things like integers. You can confirm this by typing the following in the Python-Shell:

>>> b = 42
>>> print(id(b))
505498648
>>> b = 99
>>> print(id(b))
505499560

– In line 1 we have a reference b that points to the object with value 42.
– In line 2 we check the address of the object that b is pointing to. It is 505498648.
– In line 3 we create a new object with value 99. With b = 99 the reference points now to this new object.
– In line 4 we check the address of the object b is pointing to. We see that the address is now 505499560.

Now, similarly to changeList3() we try to modify a number:

def changeNum(x):
    x+=3       # try to increase x by 3

Save this function in the file callBySharing.py and run it in the Python-Shell. Then type the following in the Python-Shell:

>>> myNumber = 77
>>> changeNum(myNumber)
>>> print(myNumber)
77

Line 4 shows that the object 77 is not changed. This is because numbers are immutable objects.

References: (no pun intended)
1. Parameter Passing
This article is part of an online Python couse.

2. Python: How do I pass a variable by reference?
This is a discussion on stackoverflow.com.

3. Is Java pass by reference?
This is a nice discussion on call by object reference, and although it is on Java the same applies to Python. I found two posts particularly helpful: post1 and post2.

Advertisements

One Response to “Call by Object Reference (Call by Sharing)”

  1. janakiraman said

    Woww. The best explanation for the “call by object reference” used in python. Thank you very much for the post. I’m newly learning python and your post really helped me to learn this concept. Also if possible can you give a list of the best python tutorials and references.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: