Learn and Learn

Learn And Learn - great place for tutorials, references and how-to

Python Mutable and Immutable Function Arguments

Python compiler handles function arguments slightly different than other popular programming languages like C, C++, and Java but much like Ruby. Python function arguments behavior is confusing when a “mutable” object, like Python dict (dictionary), set or list, is involved in the function argument list. The behavior of Python function arguments or parameters is interesting and confusing for the beginners at the same time. It is believed, this strange behavior bites once a time to almost all the beginners of Python developers in their programming life.
You need to spare some time and read this complete article with examples. It is advised that you should also read some other related articles mentioned here to understand this behavior. This will definitely help you to avoid strange circumstances in programming due to this behavior of Python function argument.

How Variables are Stored in Python

First, you need to understand how Python stores variables before we go further. This will help you to understand the behavior of Python mutable and immutable function arguments. In Python, almost everything is an object. Numbers, strings, functions, classes, modules and even Python compiled code, all are objects.

Python treats all variables as references to the object. This means all variables store the memory address of the actual object. This concept is much like “Pointer” in C and C++ programming language. This means the address of the actual object is stored in the Python named variable, not the value itself.

Furthermore, immutable and mutable objects or variables are handled differently while working with function arguments. We will discuss them in below section.
In the following diagram, variables a, b and name point to their memory locations where the actual value of the object is stored.
Python variable storage example

Immutable Objects or Variables in Python

In Python, immutable objects are those whose value cannot be changed in place after assignment or initialization. They allocate new memory whenever their value is changed. Examples of immutable data types or objects or variables in Python are numbers (integers, floats), strings and tuples.
python immutable variable storage example

In above diagram, the value of variable b is changed from 11 to 8 after its assignment or initialization. b is an integer and it is an immutable variable. Hence, new memory is allocated for it and old is discarded. In other words, you can never overwrite the value of immutable objects. Every time you change the value of an immutable object, a new object is created in result. Old object is discarded and memory is cleaned up by garbage collector automatically for later use. So in first look, this seems inefficient but in practical it is not. This technique is also used in other very popular platforms like Java and .NET.

Immutable Object or Variable Example with Explanation in Python


Result:
Value of x: 10
ID of x before modification: 1528383264

Value of x: 20
ID of x after modification: 1528383584

Explanation:

  • As you can see memory address of x is changed after modification of value of x variable. This is clear that new memory location is allocated after modification of value of variable x

Mutable Objects or Variables in Python

In Python, list, dict and set are examples of mutable data types. Their values can be changed in place after their assignment or creation. When the value of a mutable variable is changed its memory is not reallocated.

Python mutable and immutable example

In the above diagram, individual string objects in the my_list are immutable but my_list itself is mutable. If we add, remove or modify individual string elements in my_list, the my_list variable points to same object.

Mutable Object or Variable Example with Explanation in Python


Result:
my_list: ["apple", "pear"]
ID of x before modification: 19925552
my_list: ["apple", "pear", "banana"]
ID of x after modification: 19925552

Explanation:

  • As you can see, memory address of variable is not changed after modifying the object my_list
  • This has been discussed in detail with examples in this article below.

Major Concepts of Function Argument Passing in Python

Arguments are always passed to functions by reference in Python. The caller and the function code blocks share the same object or variable. When we change the value of a function argument inside the function code block scope, the value of that variable also changes inside the caller code block scope regardless of the name of the argument or variable. This concept behaves differently for both mutable and immutable arguments in Python.

In Python, integer, float, string and tuple are immutable objects. list, dict and set fall in the mutable object category. This means the value of integer, float, string or tuple is not changed in the calling block if their value is changed inside the function or method block but the value of list, dict or set object is changed. Consider the mutable and immutable as states of the function arguments in Python. Let’s discuss it in detail with examples in the following section.

Python Immutable Function Arguments

Python immutable objects, such as numbers, tuple and strings, are also passed by reference like mutable objects, such as list, set and dict. Due to state of immutable (unchangeable) objects if an integer or string value is changed inside the function block then it much behaves like an object copying. A local new duplicate copy of the caller object inside the function block scope is created and manipulated. The caller object will remain unchanged. Therefore, caller block will not notice any changes made inside the function block scope to the immutable object. Let’s take a look at the following example.

Python Immutable Function Argument – Example and Explanation

Result:
id of a: 1456621360
x: 10
y: 11
id of x: 1456621344
id of y: 1456621360


Explanation:

  • Original object integer x is immutable (unchangeable). A new local duplicate copy a of the integer object x is created and used inside the function foo1() because integers are immutable objects and can’t be changed in placed. The caller main block where variable x is created has no effect on the value of the variable x.
  • The value of variable y is the value of variable a returned from function foo1() after adding 1.
  • Variable x and y are different as you can see their id values are different.
  • Variable y and a are same as you can see their id values are same. Both point to same integer object.

Python Mutable Function Arguments

Python mutable objects like dict and list are also passed by reference. If the value of a mutable object is changed inside the function block scope then its value is also changed inside the caller or main block scope regardless of the name of the argument. Let’s take a look at the following diagram and code example with the explanation at the end when we assign list1 = list2.

Python mutable objects

Python Mutable Function Argument – Example and Explanation

Result:
original list: [10, 20]

list1 id: 24710360
value of list2: [10, 20]
list2 id: 24710360

after foo2(): [10, 20, 30]
list1 id: 24710360
value of list2: [10, 20, 30]
list2 id: 24710360

after foo3(): [10, 30]
list1 id: 24710360
value of list2: [10, 30]
list2 id: 24710360

after foo4(): [100, 30]
list1 id: 24710360
value of list2: [100, 30]
list2 id: 24710360


Explanation:

  • We have created a list object list1 and assigned same object to a new variable list2. Now both list1 and list2 points to the same memory where actual list object [10, 20] is stored.
  • We passed the value list1 variable into the function argument func_list. We appended, deleted and modified the list1 object element in function foo2(), foo3() and foo4() through argument func_list.
  • As you have noticed that actual object list1 is changed in the main block when we changed its value in the function block.
  • You should also notice that the value of list2 variable also changes when the value of list2 changes. As we have also read, this is because both list1 and list2 variable points to same list object [10, 20].
  • list1 object ID doesn’t change after every call to function foo2(), foo3() and foo4(). This is because list1 is mutable and can be modified. Therefore, changing list1 object modifies original object value and doesn’t create the new object.

Now, we discuss the most interesting and confusing part of Python function arguments which is default mutable function arguments. First, we discuss about default function arguments then mutable default function arguments.

 

Loading...
LearnAndLearn.com © 2018 - All rights reserved