How To Pass a Variable By Reference In Python?

Summary: Variables are passed by object reference in Python. Therefore, mutable objects are passed by reference while immutable objects are passed by value in Python. To pass immutable objects by reference you can return and reassign the value to the variable, or pass it inside a dictionary/list, or create a class and use the self variable for reference.

Problem: How to pass a variable by reference in Python?

In order to use functions and classes in Python or any other programming language, it is extremely important that we understand how a function call works based on a Call By Reference or Call By Value or Call By Object Reference. Let us discuss these concepts one by one before we reach the final solution.

Fundamentals Of Call By Value

In the call by value method, the value of an argument is copied into the parameter of the function. Hence, any changes made to the parameter inside the called function are not reflected in actual parameters of the caller function because the variable inside the called function and the caller function refers to two different locations in the memory.

Example:

def func():
  a = 10
  print("Before Function call value of a = ",a)
  increment(a)
  print("After Function call is over value of a = ",a)
  print("Identity of a in func() is ",id(a))

def increment(k):
  a = k+10
  print("Inside function call Value of a = ",a)
  print("Identity of a in increment() is ",id(a))
  return a

func()

Output:

Before Function call value of a =  10
Inside function call Value of a =  20
Identity of a in increment() is  140578841094464
After Function call is over value of a =  10
Identity of a in func() is  140578841094144

Fundamentals Of Call By Reference

In the Call by reference method, the address of the argument is passed to the called function. Thus we are referencing the address of the variable in this case and any alterations made in the parameter inside the function are also reflected outside the function.

Call by reference is supported by languages like Java. Let us have a look at a small java program to visualize the working theorem of the call by reference method. ( I am deliberately using Java here so that we can compare and contrast the differences when we discuss Call By Object Reference Method using Python in a while.)

public class Reference{  
 int data=10;  
 
 public static void main(String args[]){  
   Reference obj=new Reference();  
  
   System.out.println("before change "+obj.data);  
   obj.change(obj);//passing object  
   System.out.println("after change "+obj.data);  
  
 }
 
 void change(Reference obj){  
 obj.data=obj.data+100;//changes will be in the instance variable  
 }  
     
} 

Output:

before change 10
after change 110

To understand the difference with the Call By Reference and Call By Value Methods, please have a look at the animation given below:

Fundamentals Of Call By Object Reference

Many of you might have come across the call by reference and call by value methods of function calling but if you are a newbie in the world of Python, then probably the term Call By Object Reference is new to you. Here’s a reminder for you before we discuss how function calls work in Python – Everything is an Object in Python.

Python neither uses call by value nor call by reference. It uses call-by-object-reference / call-by-assignment that means:-

  • When a mutable object like a list is passed to a function, it performs call-by-reference.
  • When an immutable object like a number, string, or tuple is passed to a function, it performs call-by-value.

Example: The following program demonstrates the above concept where Python performs a call-by-reference in case of mutable objects like lists while call-by-value in case of an immutable object like a string:-

def refer(l):
  l.append(5)
  print("list inside function : ",l)
  return l

def value(n):
  name = "Python"
  print("Name within function : ",name)
  return name
 
li = [1,2,3,4]
print("list before function return : ",li)
refer(li)
print("list after function return : ",li)
name = "Finxter"
print("Name before function return : ",name)
value(name)
print("Name after function return : ",name)

Output:

list before function return :  [1, 2, 3, 4]
list inside function :  [1, 2, 3, 4, 5]
list after function return :  [1, 2, 3, 4, 5]
Name before function return :  Finxter
Name within function :  Python
Name after function return :  Finxter

Now that brings us to the mission-critical question:

How To Pass An Immutable Variable By Reference In Python?

This won’t be an issue in the case of mutable objects but in the case of immutable objects, we have to pull out a few tricks from our pocket to change them. Let us have a look at some of those in the next phase of our article.

Method 1: Return The New Value And Reassign

A simple workaround for passing an immutable variable like a string by reference is to accept the variable, make modifications on it, and return the value. After returning the variable, reassign the returned value from the function to the variable again since it is outside the local scope of the function.

This might be a little confusing but the following code given will make things clear for you:

def change(n):
    n = "Sayon"
    return n

name = "Shubham"
print("Name before function call is ", name)
name = change(name)
print("Name after function call is ", name)

Output:

Name before function call is  Shubham
Name after function call is  Sayon

Method 2: Passing Immutable Values Using Dictionaries Or Lists

Now, this method is a little hack to deal with a pass by reference of immutable objects. Since Python Dictionaries are mapping type objects and are mutable you can define your immutable variables inside a dictionary and then pass them to the function. Even though lists are not used for object mapping, however, you can still use them like dictionaries because the items of a list can be accessed using their index and lists are mutable.

Let us have a look at how we define a string and a number and pass them as reference using list and dictionary:

name = {'name': 'Christian'}
n = [4]
print("***Values Before Function Call***")
print("Name: ",name['name'])
print("Number: ",n[0])

def func(d):
  d['name'] = 'Mayer'

def foo(n):
  n[0] += 1

func(name)
foo(n)
print ("***Values After Function Call***")
print("Name: ",name['name'])
print("Number: ",n[0])

Output:

***Values Before Function Call***
Name:  Christian
Number:  4
***Values After Function Call***
Name:  Mayer
Number:  5

Method 3: Using Class And self Keyword

The keyword self is used to access instance attributes. We can set attributes inside __init__ and then change their value in instance methods.

Let us have a look at the following program to understand how this works for us:

class Changed:
    def __init__(self):
        self.var = 10
        print("Value before function call :",self.var)
        self.Change(self.var)
        print("Value after function call :",self.var)

    def Change(self,n):
        self.var = n+1

obj = Changed()

Output:

Value before function call : 10
Value after function call : 11

Conclusion

Following were the key takeaways from this article :-

  1. Fundamentals of Call by Value.
  2. Fundamentals of Call by Reference.
  3. Fundamentals of Call by Object Reference in Python for Mutable and Immutable Objects.
  4. Methods to pass immutable objects by reference in Python.

I hope you found this article useful. Please subscribe and stay tuned for more interesting articles in the future!