Python's Mutable Default Problem 12

Posted by tottinger Fri, 23 May 2008 03:16:00 GMT

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:

Mine
def 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.

Comments

Leave a response

  1. Avatar
    paddy3118 about 3 hours later:

    You get bit once, but have you seen anyone leave it in on purpose?

    - Paddy.

  2. Avatar
    Kevin about 5 hours later:

    So is that link up at the top supposed to point back to this article? Just curious :-)

    Kevin

    Ooops. Fixed now. Thanks. —tim
  3. Avatar
    Tim about 9 hours later:

    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.

  4. Avatar
    John Roth about 13 hours later:

    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

  5. Avatar
    matthew about 13 hours later:

    I wonder if this was a deliberate decision, to aid with recursion?

  6. Avatar
    yachris2112 4 days later:

    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:

    somevar ||= default_val

    although the ‘or’ syntax would work as well. I think the ’||’ version is a bit more noticeable.

    matthew: almost certainly not.

  7. Avatar
    JustRanting 29 days later:

    I wonder how Python and professional fit together ;-)

  8. Avatar
    tim about 1 month later:

    @JustRanting:

    I guess about like this:

    http://www.google.com/search?q=python+professional&;ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a

    Or this: http://www.google.com/trends?q=python%2C+professional&;ctab=0&hl=en

    Or maybe this: http://www.google.com/search?q=professional+python+job&;ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a

    There is actually a lot more python out there than you think there is. And probably less than I hope. ;-)

  9. Avatar
    Olivier about 1 year later:

    I know it’s late, but I came across this page from Google, so in case someone else would look into it…

    Your own “fix” is incorrect, because an empty list evaluates to False in Python, so that if you try to use your function to append some item to an existing, yet empty, list, it won’t work.

  10. Avatar
    Tim Ottinger about 1 year later:

    Excellent catch. Should have checked that it was None instead. thank you for the update!

  11. Avatar
    dvla address about 1 year later:

    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.

  12. Avatar
    gucci louis vuitton shoes about 1 year later:

    Welcome to Freshstyleshop, the hottest urban clothing site on the net! We offer great products from Gucci sneakers, prada sneakers, LV shoes, True Religion Jeans and many more! Our selection of products are always increasing for the fact that we have new items added weekly to our selection. All products on our site are already marked down 40-60% off retail price. Freshstyleshop also backs all its orders with a 110% satisfaction guarantee, making sure that our customers are left satisfied with the hottest products on the net.

Comments