Beware of default mutable arguments!
The default mutable arguments of functions in Python aren't really initialized every time you call the function. Instead, the recently mutated values are used as the default value.
The first time that the function is called, Python creates a persistent object for the mutable container. Every subsequent time the function is called, Python uses that same persistent object that was created from the first call to the function.
def some_func(default_arg=[]):
default_arg.append("some_string")
return default_arg
Output:
>>> some_func()
['some_string']
>>> some_func()
['some_string', 'some_string']
>>> some_func([])
['some_string']
>>> some_func()
['some_string', 'some_string', 'some_string']
When we explicitly passed []
to some_func
as the argument, the default value of the default_arg variable was not used, so the function returned as expected.
Output:
>>> some_func.__defaults__ #This will show the default argument values for the function
([],)
>>> some_func()
>>> some_func.__defaults__
(['some_string'],)
>>> some_func()
>>> some_func.__defaults__
(['some_string', 'some_string'],)
>>> some_func([])
>>> some_func.__defaults__
(['some_string', 'some_string'],)
A common practice to avoid bugs due to mutable arguments is to assign None as the default value and later check if any value is passed to the function corresponding to that argument. Example:
def some_func(default_arg=None):
if default_arg is None:
default_arg = []
default_arg.append("some_string")
return default_arg
Source: wtfpython
Thanks to TomKerzas for providing another excellent resource for information on this topic here