LambdaLabTM
Computer Science · Class 12 · Functions
FunctionsDefaults⏱️ 13 min read

Default Parameters

Sometimes a parameter has an obvious usual value. A rate of interest is nearly always 6.5%; a greeting is nearly always “Good morning”. A default parameter lets the definition supply that value itself, so the caller only has to mention it when it is different.

1Giving a parameter a default

default_intro.py
def greet(name, message='Good morning'):
    print(message + ',', name)

greet('Riya')                      # message is left out
greet('Amit', 'Good evening')      # message is supplied
Output
Good morning, Riya
Good evening, Amit

The = in the definition is what makes it a default. Read it as “if nobody tells me, use this”. The first call passes one argument and the second passes two, and both are legal calls of the same function.

Key Takeaway
A default makes an argument optional, not the parameter. Inside the function message always has a value — either the one the caller gave or the one the definition provides. The body never has to check.

2Several defaults at once

interest.py
def interest(principal, rate=6.5, years=1):
    return principal * rate * years / 100

print(interest(20000))               # rate 6.5, years 1
print(interest(20000, 7.5))          # rate 7.5, years 1
print(interest(20000, 7.5, 3))       # all three supplied
Output
1300.0
1500.0
4500.0

One function, three sensible ways to call it. Arguments still fill the parameters left to right, so supplying two means you have set principal and rate — there is no way to skip rate and set only years this way.

3Defaults must come last

This is the rule the exam asks about, and it follows from positional matching rather than from any decision of Python's:

default_order_error.py
def f(a=1, b):
    pass
Output
  File "default_order_error.py", line 1
    def f(a=1, b):
               ^
SyntaxError: parameter without a default follows parameter with a default
Watch Out
Think about what the call would have to look like. With f(a=1, b), a call of f(5) is ambiguous: is the 5 filling a, leaving b empty — or is it meant for b? Python refuses the definition rather than guess at the call. So: all parameters without defaults first, all parameters with defaults after them.
Legal
def f(a, b) def f(a, b=2) def f(a, b=2, c=3) def f(a=1, b=2)
SyntaxError
def f(a=1, b) def f(a, b=2, c) def f(a=1, b, c=3)

4Skipping one: name it at the call

To set years without touching rate, name the argument at the call. Python then matches by name instead of position:

keyword_args.py
def interest(principal, rate=6.5, years=1):
    return principal * rate * years / 100

print(interest(20000, years=3))                     # rate stays at 6.5
print(interest(principal=20000, years=3, rate=7.5)) # order no longer matters
Output
3900.0
4500.0

These are keyword arguments. Notice the second call lists them in a different order from the definition and still works — because once you name them, position has nothing left to decide. Named arguments must come after any positional ones.

5The one trap worth knowing

A default value is worked out once, when the def line runs — not afresh on every call. With a number or a string you would never notice. With a list you will:

default_evaluated_once.py
def add_item(item, basket=[]):
    basket.append(item)
    return basket

print(add_item('pen'))
print(add_item('book'))
print(add_item('bag'))
Output
['pen']
['pen', 'book']
['pen', 'book', 'bag']

Three separate calls, each expecting a fresh basket, all sharing one list — the one created when the function was defined. The fix is to default to None and make the real list inside:

default_safe.py
def add_item(item, basket=None):
    if basket is None:
        basket = []
    basket.append(item)
    return basket

print(add_item('pen'))
print(add_item('book'))
Output
['pen']
['book']
Tip
The short rule: never default a parameter to a list. Numbers, strings, True, False and None are all safe, because none of them can be changed in place. This is the mutable / immutable distinction from Class 11 showing up in a third place.
interest.py

6Recap

The = goes in the definition

def greet(name, message='Good morning'). It means 'if nobody tells me, use this'.

Defaults must come last

SyntaxError: parameter without a default follows parameter with a default — because f(5) would otherwise be ambiguous.

Name an argument to skip one

interest(20000, years=3) leaves rate at its default. Named arguments come after positional ones.

Never default to a list

The default is made once, at def time, and every call shares it. Default to None and build the list inside.

✍️ Now write these yourself
  1. 1

    Write area(length, breadth=1) and call it both ways.

    Hint · area(5) gives 5 and area(5, 3) gives 15 — a default of 1 turns it into a length.

  2. 2

    Write def f(a=1, b) deliberately and read the error.

    Hint · Worth seeing once, so the wording is familiar when it happens for real.

  3. 3

    Write a function with three parameters, two of them defaulted, and call it four different ways.

    Hint · One argument, two, three, and one using a keyword argument to skip the middle parameter.

  4. 4

    Run the basket=[] example, then fix it with basket=None.

    Hint · The first grows across calls; the second starts empty each time. Seeing both is the point.

Quick Check

Why is `def f(a=1, b):` a SyntaxError?

Quick Check

What does interest(20000, years=3) do to rate?

Quick Check

Why does `def add_item(item, basket=[])` grow across separate calls?