Mutable objects vs Python functions.
We know every thing in python is an object and can be classed into mutable and immutable, where mutable object are object whose state can change after construction while the latter are object whose state cannot be change after construction.
code snippet made pretty by https://carbon.now.sh
Both Dictionary and List in python are mutable, therefore caution should be taken when passed as an argument to functions because they are passed by reference and not by value, meaning that when passed to a function as an argument the object is referenced and a copy of the object is not created which might cause a bug depending on what you’re trying to achieve with your code.
Here is a code snippet to understand what is happening when you pass a mutable object to a function.
code snippet made pretty by https://carbon.now.sh
In this code snippet above, i have a variable “leader_board” that references a dictionary object which hold a data of leaderboard score, also there is a function which add a new member to my leader board, the function “add_new_member” accepts a dictionary object of the leaderBoard, the name of the new member and the score, when this function is called and passed in the “leader_board” object, the name of the new member (‘janet’) and the score (12).
leader_board[name] = score
This state above within the function add a new key:value pair data to the leader board object in memory.
when the function “add_new_member” is called it reference the leader_board object in memory and change the value in-place, when the leader_board is printed within the function we get.
{‘james’:23, ‘doe’:20, ‘mat’: 15, ‘janet‘: 12}
Also when the leader_board object is print out side the function we get the same result. To confirm this let run an object test by updating the code to return the leader_board from the function and use the “is” operator to do object test.
code snippet made pretty by https://carbon.now.sh
print(result is leader_board)
This above statement will return True because the “is” operator is checking if the two operands i.e result and leader_board are referencing the same object and are of equal value equal.
I also added a new block of code below in the codebase to show that the “is” operator actually does what it does the “print( leader_board is leader_board_2)” will return False because the two are different object in the memory, even if they have the same data they must reference the same object.
Overriding the universe
Mutable object being passed by reference to a function might be useful in must cases but what if that not how i want my code to behave, what if i want my code to accept a mutable object and return a new one without affecting the result of the one passed to it, the solution is to use the “copy()” method provided by mutable objects, the copy function return a shallow copy of the object and that can be assigned to another variable.
code snippet made pretty by https://carbon.now.sh
With the new updated codebase above now using “copy” method with the mutable object, return a shallow copy of the data and create a new object in memory , and you can see that our “result” object is different from the “leader_board” object, when we do an object test “print(result is leader_board)” we get False to show that they are not the same object in memory.
Note: the whole story above apply to List object as well, it also mutable.
Conclusion
So depending on what you’re trying to achieve with you code know when to really on mutable object being passed by reference and when to override the behaviour else 😢 🐛 🐛 😢.
Don’t forget to share this with your fellow pythonistas you might save a soul.
Thank you.