How Call by Value and Call by Reference Work in Python?

In this Article we're going to understand how call by value and call by reference work in python

Let's first understand what is call by value and call by reference

  • Call By Value :- In Call by value the value(copy) of the parameters passed as formal argument ina function instead of the variable itself, so in this case if any modification applied to the function parameters it will not be reflected on the actual variable.**

let's take example in C programming langauge to better understand call by value and call by reference
Example :-

#include <stdio.h>

void call_by_value(int a , int b){
    a = 44;
    b = 55;
}

int main() {
    int a  = 1;
    int b = 2;
    printf("value of a and b before function call :- %d and %d",a,b);
    call_by_value(a, b);
    printf("\nvalue of a and b after function call :- %d and %d",a,b);
    return 0;
}
Output :-
value of a and b before function call :- 1 and 2
value of a and b after function call :- 1 and 2

In above example the value of varible a and b not modified because a copy of a,b passed instead of their addresses

  • Call By Reference :- In Call By Reference, the address(actual varible) of the variable is passed into the function call as the actual parameter.

So, if any modification applied to the function parameters it will be reflected on the actual variable.**

Example :-

#include <stdio.h>

void call_by_reference(int *a , int *b){
    *a = 44;
    *b = 55;
}

int main() {
    int a  = 1;
    int b = 2;
    printf("value of a and b before function call :- %d and %d",a,b);
    call_by_reference(&a, &b);
    printf("\nvalue of a and b after function call :- %d and %d",a,b);
    return 0;
}
Output :-
value of a and b before function call :- 1 and 2
value of a and b after function call :- 44 and 55

In above example the address of varible a and b using & followed by variable name , where in function defination
* followed parameter known as pointer variable which used
to storing addresses, because of this values in varible a and b is modified.

Now we have seen what is call by value and call by reference with example

But, Python programming language uses the mechanism of the call-by-object and also call by object reference.

Each object whenever it is instantiated ,it is assigned unique id and its type if defined at runtime and id(object) returns a unique identity (integer value) of that object.

to move further into the topic first we have to understand mutable object and immutable object in python.

  • Mutable Objects
    Datatypes that can be modified or if there state can be changed those objects are known as Mutable datatype
    like (list, dictionaries, set) .

  • Immutable Objects
    Datatypes that cannot be modified or if there state cannot be changed those objects are known as Immutable datatype like **(int, float, bool, string, unicode, tuple).

So when Mutable objects are passed to the function call then it is treated as **call by value.**

And When Immutable objects are passed to the function call and there value is modified then it is treated as **call by reference.**

For the sake of simplicity we're going to use the word call by value and call by reference instead of (call by object) and (call by object reference) respectivly.

let's take examples for call by reference and call by value

Example :- Call by reference (with Immutable objects (int, float, bool, string) and no object state modified) in python

num1  = 43
num2 = 12.44
num3 = False
name = 'hello'
print("Id in main function scope")
print(f"id of num1  = {id(num1)}")
print(f"id of num2  = {id(num2)}")
print(f"id of num2  = {id(num3)}")
print(f"id of name = {id(name)}")


def call_by_reference(num1,num2,num3,name):
  print("\nId within function")
  print(f"id of num1  = {id(num1)}")
  print(f"id of num2  = {id(num2)}")
  print(f"id of num2  = {id(num3)}")
  print(f"id of name = {id(name)}")


call_by_reference(num1,num2,num3,name)

Output :-
Id in main function scope
id of num1  = 94157957099328
id of num2  = 140438713493200
id of num2  = 94157956423968
id of name = 140438848940272

Id within function
id of num1  = 94157957099328
id of num2  = 140438713493200
id of num2  = 94157956423968
id of name = 140438848940272

So we can see that the id's the objects (num1, num2, num3) has not change becuase have not applied modification to those objects.

Example :- Call by reference (with Mutable objects (list ,dict) and object state modified) in python

names = ['ram', 'shyam', 'bharat']
d =  {'bob':21,'max':22}
print("Id in main function scope")
print(f"id of names list  = {id(names)}")
print(f"id of d dict  = {id(d)}")

def call_by_reference(name, d):
  print("Id within function")

  d['sam'] = 12
  names.append('john')

  print("\nModified Objects id :-")
  print(f"id of names list  = {id(names)}")
  print(f"id of d dict  = {id(d)}")

call_by_reference(names, d)
print("Modfied list and dict")
print(f"names =   {names}")
print(f"dict = {d}")

Output :-

Id in main function scope
id of names list  = 140439297460096
id of d dict  = 140438712179600
Id within function

Modified Objects id :-
id of names list  = 140439297460096
id of d dict  = 140438712179600
Modfied list and dict
names =   ['ram', 'shyam', 'bharat', 'john']
dict = {'bob': 21, 'max': 22, 'sam': 12}

We can see even after modifying the objects state the id's of the object remains unchanged because the objects datatype are mutable objects here by ,even if the object state is modified
it is treated as call by reference(call by object reference).

==============================================

Example :- Call by Value (with Immutable objects (int, float, bool, string) and object state modified) in python

num1  = 43
num2 = 12.44
num3 = False
name = 'hello'
print("Id in main function scope")
print(f"id of num1  = {id(num1)}")
print(f"id of num2  = {id(num2)}")
print(f"id of num2  = {id(num3)}")
print(f"id of name = {id(name)}")


def call_by_value(num1,num2,num3,name):
  print("\nId within function")
  num1 = 1
  num2 = 2
  num3 = 3
  name = 'sam'
  print("Modified Objects id")

  print(f"id of num1  = {id(num1)}")
  print(f"id of num2  = {id(num2)}")
  print(f"id of num2  = {id(num3)}")
  print(f"id of name = {id(name)}")


call_by_value(num1,num2,num3,name)
print("\Unmodified int, float, bool, string objects value in global scope")
print(f'num1 = {num1}')
print(f'num2 = {num2}')
print(f'num3 = {num3}')

Output :-
Id in main function scope
id of num1  = 94157957099328
id of num2  = 140438713494320
id of num2  = 94157956423968
id of name = 140438848940272

Id within function
Modified Objects id
id of num1  = 94157957097984
id of num2  = 94157957098016
id of num2  = 94157957098048
id of name = 140438713157936

Unmodified int, float, bool, string objects value in global scope
num1 = 43
num2 = 12.44
num3 = False

In the above example we can see that after modifying the Immuatable objects the object id's were diffrent , this is because we cannot modify the value of Immutables and because of this new 3 objects named (num1, num2, num3, name) where created in the function local scope after the function call we have also print the value to verify the objects in the global scope remain unchanged.

Example :- Call by Value (with Immutable objects (tuple) and object state modified) in python

names = ('ram', 'shyam', 'bharat')
print("Id in main function scope")
print(f"id of names tuple  = {id(names)}")

def call_by_value(name, d):
  print("Id within function")
  names = ('ram','shyam','bharat','john')
  print(f"modified object value \n{names}")
  print("\nModified Objects id :-")
  print(f"id of names tuple  = {id(names)}")

call_by_value(names, d)
print("\nUnchanged tuple object in global scope")
print(f"names = {names}")

Output :-
Id in main function scope
id of names tuple  = 140438712974144
Id within function
modified object value 
('ram', 'shyam', 'bharat', 'john')

Modified Objects id :-
id of names tuple  = 140438712255888

Unchanged tuple object in global scope
names = ('ram', 'shyam', 'bharat')

In the above example we can have assigned a new tuple with same elements + one more element because (tuple datatype does not support any add method) andchecked the object id which is diffrent because a new object gets created and also the global object remain unchanged because of it's Immutable nature.

With this example we have come to an end
hope you all have understood the topics
covered in this article.

:-)

24