Keyword arguments (“kwargs”) are handy. A former colleague (thanks!) once warned me about a kwargs gotcha that I didn’t know about. I thought “let’s add the warning to my Django book”, but it is a bit too specialistic and it detracts too much from the main flow of the text. So I’m taking it out and posting it here. (It is also quite hard to explain; I’m still not quite happy with this text. But I’m not going to do more tweaking.)
Watch out with the type of default parameters for keyword arguments!
Technically: immutable types are fine, mutable types not. In plain language it
means that name='thatcher'
, amount=5
and template=None
are all
fine.
But don’t use lists or dictionaries. In Python, a variable name is just a
pointer to a memory address. If you do something like amount = amount + 4
,
amount
would start pointing at a new memory adress. Just open a Python
prompt and type in the following piece of code to test it out:
>>> def example(immutable=5, mutable={'amount': 0}):
... print immutable
... print mutable
... mutable['amount'] += 10
...
>>> example()
5
{'amount': 0}
>>> example()
5
{'amount': 10}
>>> example()
5
{'amount': 20}
We probably wanted to pass in a dictionary with some defaults already in place. However, this backfires because we’re changing values inside the very same dictionary that our keyword points to by default.
The problem is that every variable in Python is only a memory pointer to a value. With an immutable value, a new value means a fresh pointer. The contents of a mutable value, like a list, can be changed in-place without the pointer to the actual list changing; that is the whole point of them.
The solution is straightforward once you’ve seen it. For dictionaries and
lists where you want a default, pick None
as the default value and check
for that like this:
def example(immutable=5, mutable=None):
if mutable is None:
mutable = {'amount': 0}
mutable['amount'] += 10
So there you have it!
My name is Reinout van Rees and I program in Python, I live in the Netherlands, I cycle recumbent bikes and I have a model railway.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):