# Primer on Optional Parameters

You are not logged in.

Note that this link will take you to an external site (https://shimmer.mit.edu) to authenticate, and then you will be redirected back to this page.

When defining a function, sometimes we want to be able to call the function with or without a particular argument. Optional arguments allow us to do just that. Consider this example:

def approximately_equal(x, y, threshold=0.1):
return abs(x - y) <= threshold


If threshold is specified (e.g., approximately_equal(x, y, 1e-6) or approximately_equal(x, y, threshold=1e-6), then that value will be used for threshold (in this case, 10^{-6}). If not (e.g., approximately_equal(x, y)), then the default value (0.1) will be used for threshold.

In other words, if we provide the optional argument, it overrides the default value.

If a function has both required and optional parameters, all the required parameters have to come first, followed by the optional ones.

There is a small caveat here (and often a big source of bugs): default values are evaluated at the time the function is defined, not when the function is called. So we have to be careful when using a mutable object as a default value for a parameter; if we do this, all calls to the function will use that same object (which may have been modified by previous calls).

For example,

def foo(x, y=[]):
y.append(x)
return y

print(foo(4))  # prints 
print(foo(5))  # prints [4, 5] !!!


To avoid the problem of mutable default arguments, assign your default argument to some kind of immutable value (like None), and then initialize it to your desired mutable structure within the function.

def foo(x, y=None):
if y is None:
y = []
y.append(x)
return y

print(foo(4))  # prints 
print(foo(5))  # prints