Pass by value, pass by reference and what Python does

We discussed the concept of reference in Introduction to Classes. A reference stores the address of an object on the heap as opposed to a variable that stores the data itself. In this lesson, we will see some interesting differences between passing a variable or a reference to a function as an argument.

Passing copy of data (pass by value)

Since a variable directly stores the data, when a function is called with a variable as an argument, a copy of the data is made for the called function. Consequently, if the function makes any changes to the data, the changes are applied to this copy of the data and the original data in the calling function is not affected. By default, this is how the primitive data types in C# such as integers, floats and bools are passed to a function.

C# code

Since  num1 is an integer, a copy of the data is made when the integer is passed to the function  incrementNumber(). Therefore, any changes the function applies to its parameter are local to the function and the value of  num1 in the calling function is not affected.

Passing copy of reference (what Python does)

When a function is called with a reference as an argument, a copy of the reference is made for the called function. However, no copy is made of the data on the heap addressed by this reference. Therefore, both the original reference and the copied reference contain the address of the original data. Consequently, any modifications that the function does to the data occur on the original data and are visible to calling function as well. However, if we assign a new address i.e. a new object on the heap to the copy of reference, the original reference in the calling function still contains the address of the original data. By default, this is how the built-in and user defined Objects are passed to functions in C#. Since any data in Python is an object, Python always uses this technique of passing arguments to functions.

C# code

When the two lists are passed to the function  calculateGrades(), only a copy of their references is made. The reference  grades_maths in the Main() function and grade_list in calculateGrades() function refer to the same list object on the heap. Therefore, when new grades are added to the list inside the function  calculateGrades(), the changes are visible in the Main() function as well. However, when we assign a new object to the reference grade_list, the reference grades_maths in the  Main() function still refers to the original object and the data is not lost. The Python code for the same example is given below.


Output: List of grades.

The ref keyword (pass by reference)

C# provides a third way of passing arguments to functions. We can pass variables or references to a function such that neither the data nor the reference is copied for the called function. In this case, any modifications that the function makes to the data or the reference (if a reference is passed) are visible in the calling function. This means even when the function assigns a new object to the reference, it is updated in the calling function as well and the address of the previous object is lost.

The only difference to the above example is that the list of scores is passed with the  ref keyword. This makes the assignment of a new object to that list visible to the calling function and therefore the list of scores contains all zeros after the  calculateGrades() function has been called.


Output: the use of ref keyword

< Difference between lists and dictionaries               Polymorphism >

You may also like: