Moredreads Blog

Game Announcement: Qubarchy

Two weeks ago Eduard and I began to work on a open source real time strategy and exploration game named qubarchy. I hope we get out a public version soon. :)

Disqus Enabled

Although I despise external webservices (e.g. because of privacy and reliability problems) I’ll activate octopress’s disqus feature for now.

Python Pitfall With Mutable Default Parameters

We stumbled upon an unexpected way default parameters work while writing python code for our current game project.

In Python you can specify a default value for a function parameter, which is used when the function is called with less parameters than the function needs.

1
2
3
4
5
>>> def printHello(text="Hello World!"):
...  print text
>>>
>>> printHello()
Hello World!

In python strings are immutable, that means you can’t change it after creation. When you for example concatenate two strings a new one is created, so there is no way to change the default parameter string.

But what happens if you use an empty list as the default parameter? I expected to always get an empty list.

So the following function should always print the same.

1
2
3
4
5
6
7
>>> def append_one(values=[]):
...   values.append("One")
...   print values
>>> append_one()
['One']
>>> append_one()
['One', 'One']

What happens here?

A list is mutable, that means you can add or change elements in the list. And you get passed the same list instance each time on a call to append_one, as variables are passed by reference in python. So this behaviour is actually not that surprising. The same is the case for each other mutable class you pass as a default argument.

But how can you use a mutable object?

There are several ways, but I like the following.

Instead of passing the object directly, we pass None and check for it in the function.

1
2
3
4
5
6
7
8
9
10
11
>>> def append_one(values=None):
...     values = values or []
...     values.append("One")
...     print values
...
>>> append_one()
['One']
>>> append_one()
['One']
>>> append_one(['Zero'])
['Zero', 'One']

We also used the compact or notation, see the Python documentation for how that works.

Hello World!

Hey, yet another blog is born to the interwebz!!111