python: default argument blunders

A few minutes ago a friend sent me the following code, and told me its misbehaving:

def foo(l=[]):
l.append("hello!")
print(l)

foo()
foo()

Instead of printing ["hello"] twice, it printed ["hello", "hello"]. Any ideas why?

what’s going on?

I’ll start of by saying that setting an empty list as a default parameter, is a common gotcha in python.

l is a list, and lists are mutable in python (as opposed to some other languages, like elixir). default parameters are initialized at parsing time, so our l parameter got initialized once, not on every call. Interesting right? You can read more here.

The fix is quite trivial, and you’ll see it a lot in production code:

def foo(l=None):
# l might be an empty list
if l is None:
l = []
l.append("hello!")
print(l)

By the way, if you want to avoid common gotchas, likely bugs & design problems in your code, I suggest installing flake8-bugbear. It works out of the box when you’ve got flake8 configured with Neomake or Syntastic.