Python's Mutable Default Problem 7
Today I was perusing a very fine python article all professional python programmers should read. I had to grin when I saw one of my favorite python quirks/flaws.
Python only evaluates default parameters when it defines a function, leading to surprising side effects (example from saifoo):
def function(item, stuff = []):
stuff.append(item)
print stuff
function(1)
# prints '[1]'
function(2)
# prints '[1,2]' !!!
The grin on my face was because I was bit by this one again last Tuesday. You just don’t want to make a mutable object a default parameter. The solution I used was close to the solution from saifoo:
Saifoo.net:
def function(item, stuff=None):
if stuff is None:
stuff = []
stuff.append(item)
print stuff
This, of course, gives the correct behavior because it creates a new empty list each time it is called without a second parameter.
My solution actually combines some advice contained earlier in the article with the solution given for this problem:
Minedef function(item, stuff=None): stuff = stuff or [] stuff.append(item) print stuff
It’s not necessarily prettier, and I struggle with whether it is more obvious (to a Python programmer) or not. I fear it may be clever (a word I only use in the pejorative sense), but it is also clean-looking to me.
The point remains, though, that the mutable default parameter quirk is an ugly corner worth avoiding, and I suspect that any code that purposefully exploits that behavior to populate a structure that persists across calls will run a very real risk of being misunderstood.
We all know what happens when the next programmer to touch a program misunderstands it.

You get bit once, but have you seen anyone leave it in on purpose?
- Paddy.
So is that link up at the top supposed to point back to this article? Just curious :-)
Kevin
I’ve not used it on purpose. So far as I know, I’ve not seen it used on purpose. I’ve accidentally used it a few times. The tinker in me wants to try using it on purpose, and the professional refuses. Yet another case of ambivalence.
Two comments. First, the or isn’t a hack. It’s a standard Python idiom, although it looks a bit strange to someone who doesn’t have a lot of Python experience.
Second, having a mutable object as a parameter is definitely a gotcha for most Python programmers. The interesting thing is that it could be used as a way of getting a persistent variable into a method (local in some languages). However, I’ve never seen it used that way, and I’d be a bit leery of doing it myself except in programs that are part of a project where all the developers are comfortable with the idiom, and where the code isn’t expected to leave the project.
John Roth
I wonder if this was a deliberate decision, to aid with recursion?
Once again, I have to point out that Lisp had this first :-). I remember (way) back in the day having this explained to me by none other than David Moon. For pythonistas, this is like seeing a noob post responded to by Guido.
Anyway, Ruby has a similar idiom:
although the ‘or’ syntax would work as well. I think the ’||’ version is a bit more noticeable.
matthew: almost certainly not.
I wonder how Python and professional fit together ;-)