A member of the platform recently stumbled upon a bug in his python code. Once we got to the bottom of it, we were surprised to find that the bug in question had been caused by a peculiar behavior of Python.

Let’s take the following code as example :

def foo(bar=[]):     
    bar.append('a')
    return bar

Intuitively, this piece of code might seem like it ought to return the list ['a'whenever it is run. In practice, it is not quite so.

>>>foo()
['a']
>>>foo()
['a','a']
>>>foo()
['a','a','a']

As we can see, the list is not reset at each iteration but rather keeps its previously appended values. This behavior is due to the fact that python functions are also objects themselves. The function, along with its arguments, is therefore evaluated once when it is defined, and not at every call.

This is not only the case only for list arguments. Any mutable type arguments such as dicts, sets, lists, byte arrays and even functions themselves will follow the same behavior.

I was somewhat shocked that I had never stumbled upon this myself as this is hailed as a common stumbling block for newcomers to Python. Perhaps an unconscious habit of setting empty default arguments to None and handling them later on in the function had prevented me from falling into a similar situation.