Optional arguments in python are obviously very useful allowing you to have default values so you don’t need to pass them every time. A simple hello world example always goes a long way…
def hello(to="world"):
print "Hello,", to
>>> hello("Steve")
Hello, Steve
>>> hello()
Hello, world
Sometimes you’ll see people define an optional argument with a default value of None then override it in the function’s body. This might seem a strange thing to do at first, but there is a reason. Let’s say that we wanted to be able to say hello to a list of people and for it to automatically add “World” to the list.
def hello(to=[]):
to.append("World")
if len(to) > 1:
greeting = "Hello, " + ", ".join(to[:-1]) + " and " + to[-1]
else:
greeting = "Hello, " + to[0]
print greeting
>>> hello(["Steve", "Matt"])
Hello, Steve, Matt and World
>>> hello(["Steve", "Matt"])
Hello, Steve, Matt and World
>>> hello()
Hello, World
>>> hello()
Hello, World and World
>>> hello()
Hello, World, World and World
This happens because the value for the default argument is the same list every time, so when we modify it the function has the same modified list as the default argument when it is subsequently called. This is probably not the behaviour you would expect and you would rarely want to use this behaviour. The way around it is to define the default argument as None then override it.
def hello(to=None):
to = to or []
to.append("World")
if len(to) > 1:
greeting = "Hello, " + ", ".join(to[:-1]) + " and " + to[-1]
else:
greeting = "Hello, " + to[0]
print greeting
>>> hello()
Hello, World
>>> hello()
Hello, World
>>> hello(["Steve", "Matt"])
Hello, Steve, Matt and World
>>> hello(["Steve", "Matt"])
Hello, Steve, Matt and World
Because None evaluates to false, setting the default value to None means it can be easily overridden to give us the default value we actually want if there wasn’t a passed value.

