There has been much talk about “passing by reference” and “passing by value” in Python and a number of other programming languages. Let’s dispel a couple myths and talk about how Python passes parameters between methods.

Python does a thing called passing by assignment. See the following block of code:

my_var = 25
 
def my_method(v):
	v += 10
	return v

With passing by assignment, executing my_method(my_var) is identical to doing this:

my_var = 25
 
v = 25
v += 10

Nobody would expect my_var to contain the value 35 after the above code.

This is essentially what happens when we call a method in Python, but there is one important question: what is 25?

What is 25?

25 is an object! In Python, pretty much everything is an object.

In Python when both variables my_var and v are equal to 25, they are both equal to the same object.

However, you cannot change 25. The object is immutable.

When we do v += 10, really what we are doing is assigning to v a completely different object—35. We are not changing the original 25. This is why my_var stays as 25, because the object itself has not changed.

Which objects are mutable?

Lists, for example. We can directly modify a list, without having to go through an assignment.

my_list = [12, 34, 55]
x = my_list
x.append(65)

At the end of the code block, my_list would contain 4 elements. That’s because both x and my_list were the same object (as in the integer example). Changing the object means that both variables see the change.

Dictionaries are also mutable. This means we can do things like these:

my_dict = {'key': 'value'}
 
def m(d):
	d['key'] = 123
 
print(my_dict)  # prints {'key': 'value'}
m(my_dict)
print(my_dict)  # prints {'key': 123}

In Python, some built-in types are immutable:

  • numbers (int, float, etc…)
  • booleans
  • strings
  • tuples
  • frozensets

But most other types are mutable.


Hopefully, this article dispelled the “passing by value” and “passing by reference” myths in Python. Instead, what matters is whether the object we are passing is mutable, or not.

Also remember, we can still do the following:

my_list = [12, 34, 55]
 
def m(list_var):
	x = list_var + [67]
	return x
 
print(m(my_list))  # prints [12, 34, 55, 67]
print(my_list)  # prints [12, 34, 55]

That’s because when we do [12, 34, 55] + [67] that creates an entirely new list—we are no longer changing the list_var object!

For more examples, see: http://stackoverflow.com/a/986145/1587271