Overview
Hello World! This was the first bug i have put into production environment after I started using Python. Like any other production issue, i have deployed the code changes i did on Friday afternoon and when i was planning to leave home in the evening, this bug started to show its ugly face. It's a bug due to using mutable default arguments into functions in Python. For a person who is a beginner in Python from Java world, this bug was quite confusing.
Issue
Let me put down the closer version of code which caused this issue.
def save_world(key, name, tools = {}):
print('I am {}, fighting to save the world'.format(name))
tools[key] = name
# Other logic goes here
return tools
mission1 = save_world('user1' , 'Nithila')
# Output: I am Nithila, fighting to save the world
mission2 = save_world('user2' , 'Bowrna')
# Output: I am Bowrna, fighting to save the world
Expected behaviour i thought
I assumed that on each call to save_world
function, the tools variable will be initialised with empty dictionary and filled with values. I expected the output to look like below:
print(mission1)
{'user1': 'Nithila'}
print(mission2)
{'user2':'Bowrna'}
Actual behaviour and the output is:
print(mission1)
{'user1': 'Nithila'}
print(mission2)
{'user1': 'Nithila', 'user2': 'Bowrna'}
print(mission1) # Tried printing mission1 again and this is the result. Woah! both mission1 and mission2 #points to same result.
{'user1': 'Nithila', 'user2': 'Bowrna'}
print(id(mission1))
4582230208
print(id(mission2))
4582230208
Under the hood in Python, default mutable argument tools
is initialised once and it's getting added/updated as we keep on invoking that function.
I used the response from this function and returned it to the end user via an API :( That's a security breach and added fuel into fire. PyCharm editor shows warning for default mutable argument which I didn't carefully read when in development phase. I learned this lesson hard way by putting this buggy code into production environment.
[Stackoverflow response which i found very useful] (stackoverflow.com/questions/1132941/least-a..)
Some important takeaways about Python from the stackoverflow responses are:
Functions in Python are first-class objects.
A function is an object being evaluated on its definition; default parameters are kind of "member data" and therefore their state may change from one call to the other - exactly as in any other object.
Hope you find this article useful. If there is any correction , please do share in comments. Thanks for reading :)