Python default arguments for C++ developers

Jumping into a new language can be allot of fun, but your pervious experiences may hurt you more then they help. A good example of that is jumping into Python with C++ experience and trying to use default arguments. Simply enough you say, after doing some of

def fun(a = 0):
  print a
  a = 10
  print a

fun()
fun()

You can sit back and think you have seen that all before. However, today I discovered there is actually a twist here. What do you think the following code will produce?
def fun(a={}):
  print a
  a['hello'] = 'good'

fun()
fun()

Will the hello ever appear on the standard out?

Well, this can't be a blog post about everything going according to plan, so you may have expected it already: it will print {'hello': 'good'} on the stdout! The output will be:

{}
{'hello': 'good'}

Why is a=0 and a={} so different? Well, the fine answer is "assingment to a simple can not be done without chaning it's memory position", so assinging a won't change the default, but changing an attribute of a will. So after the first call that uses the default argument, your default argument will be spoiled for future use.

Now people who don't care these kinds of caveats will just state the rule behind it: As soon as the function definition is seen by the interperter, the default parameter is initialized to a value, and that is what it will stay for the rest of the program.

Another example of this is the following code:

import random
def fun(rval = random.random())
  print rval
fun()
fun()
fun()

will print the same number 3 times.

All that is ok, so you may think: what is he blabbering on about? Well, here is the catch: as soon as the integer is changed into a proper object with it's own memory location and an assign member, everything earlier code will fail! If the assignment in the first example is handled by a class member, then you end up with changing the value in the default position and that will break the code.
So, my advise (although I'm not really a python programmer, so hats of to any guru who already pointed people to this) is to either not use default arguments or use "None" as follows:

def fun(a=None):
  if a == None:
    a = {}

As None will never become an object, it should all be safe, even when Python decides to grow up and use objects for everything ;)