Skip to content
aviral gupta

// B3.2 · ~25 min · Beginner

Default values and keyword arguments

After this lesson you can give parameters default values, pass arguments by name in any order, and read the errors Python raises when a call does not fit the definition.

Lesson 2 of 5 in B3 Functions

You will be able to

  • Give parameters default values, and call the function with or without those arguments
  • Pass arguments by keyword, in any order, after the positional ones
  • Read and fix the errors for missing, duplicate, unknown and misplaced arguments
  1. Warm-up · Activity 1 of 7

    Warm-up from lesson B3.1: what does this print?

    def half(n):
        return n / 2
    
    print(half(half(8)))
  2. Predict · Activity 2 of 7

    Predict before you read on: what does this print?

    def greet(name, greeting="Hello"):
        return greeting + ", " + name + "!"
    
    print(greet("Ada"), greet("Bo", "Hi"))
  3. Practice · Activity 3 of 7

    Give exponent a default of 2, so that power(3) squares 3 and power(2, 10) still works.

    def power(base, exponent____):
        return base ** exponent
    def power(base, exponent):
  4. Practice · Activity 4 of 7

    The arguments are named, in a different order. What does this print?

    def describe(name, age, city):
        print(name, age, city)
    
    describe(city="Bonn", name="Lea", age=30)
  5. Practice · Activity 5 of 7

    Given def f(a, b=2): return a * 10 + b, match each call to its result.

  6. Brain teaser · Activity 6 of 7

    Brain teaser. The default comes from a variable that changes later. What does this print?

    rate = 0.2
    
    def with_tax(price, tax=rate):
        return price + price * tax
    
    rate = 0.5
    print(with_tax(100))
  7. Apply · Activity 7 of 7

    Mini-task. Write travel_time(distance, speed=50, stops=0, stop_minutes=5) that returns the minutes a trip takes: distance / speed * 60, plus stop_minutes for each stop. Call it three times: with only 100, with speed=100, and with stops=2.

    Check your work against this list

Build it yourself

Read the worked example, then write the exercises. Your code runs in your browser or on your computer and is never uploaded.

Worked example

A coffee price calculator

coffee_price has three parameters, all with defaults: a plain call gives a medium coffee without extras. Each call below changes something different. Positional arguments fill size and extra_shots in order, and keyword arguments set oat_milk directly, without passing the parameters before it. Try your own order at the bottom.

main.py

def coffee_price(size="medium", extra_shots=0, oat_milk=False):
    """Return the price of one coffee in euros."""
    if size == "small":
        price = 2.5
    elif size == "large":
        price = 3.5
    else:
        price = 3.0
    price = price + extra_shots * 0.6
    if oat_milk:
        price = price + 0.4
    return round(price, 2)


print(coffee_price())
print(coffee_price("large"))
print(coffee_price("small", 2))
print(coffee_price(oat_milk=True))
print(coffee_price(extra_shots=1, size="large", oat_milk=True))

Run it with

python main.py

Output

3.0
3.5
3.7
3.4
4.5
  • coffee_price() uses all three defaults: a medium coffee for 3.0.
  • coffee_price("small", 2) fills size and extra_shots by position: 2.5 + 2 * 0.6.
  • coffee_price(oat_milk=True) skips size and extra_shots, which keep their defaults.
  • The last call names all three arguments in its own order.
Change it and run it

Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.

The first run downloads Python for your browser (up to 6.5 MB) and keeps it cached. Your code stays on your device.

Exercises

Exercise 1 of 2

Greeting with defaults

Change greet in main.py so that it has two more parameters with defaults: greeting="Hello" and punctuation="!". It returns greeting, a comma and a space, the name, and the punctuation: greet("Ada") gives "Hello, Ada!" and greet("Ada", "Hi", punctuation="?") gives "Hi, Ada?".

Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.

The first run downloads Python for your browser (up to 6.5 MB) and keeps it cached. Your code stays on your device.

Hints
  1. Hint 1

    Add the two parameters after name, each with = and its default value.

  2. Hint 2

    In the body, replace the fixed "Hello, " and "!" with the parameters.

  3. Hint 3

    def greet(name, greeting="Hello", punctuation="!"): and return greeting + ", " + name + punctuation.

Show a solution

One way to solve it. Yours can look different and still pass the checks.

def greet(name, greeting="Hello", punctuation="!"):
    """Return a greeting for name."""
    return greeting + ", " + name + punctuation


print(greet("Ada"))
Run it on your computer

Install Python 3.14 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.

main.py

def greet(name):
    """Return a greeting for name."""
    return "Hello, " + name + "!"


print(greet("Ada"))

test_main.py

from main import greet


def test_defaults():
    """greet("Ada") uses both defaults"""
    got = greet("Ada")
    assert got == "Hello, Ada!", f"greet('Ada') returned {got!r}, expected 'Hello, Ada!'"


def test_greeting_by_position():
    """greet("Ada", "Hi") replaces the greeting"""
    got = greet("Ada", "Hi")
    assert got == "Hi, Ada!", f"greet('Ada', 'Hi') returned {got!r}, expected 'Hi, Ada!'"


def test_punctuation_by_keyword():
    """greet("Ada", punctuation="?") keeps the default greeting"""
    got = greet("Ada", punctuation="?")
    assert got == "Hello, Ada?", f"greet('Ada', punctuation='?') returned {got!r}, expected 'Hello, Ada?'"


def test_all_keywords():
    """All three arguments by keyword, in another order"""
    got = greet(punctuation=".", name="Bo", greeting="Bye")
    assert got == "Bye, Bo.", f"greet(punctuation='.', name='Bo', greeting='Bye') returned {got!r}, expected 'Bye, Bo.'"

On macOS and Linux, type python3 wherever these commands say python, as in the first lesson.

Run the program:

python main.py

Run the checks (needs learnrun.py in the same folder):

python learnrun.py test
Download learnrun.py

Exercise 2 of 2

Shipping costs

shipping(weight, express=False, country="DE") returns the cost in euros. The base price is 5 up to 2 kg, 8 up to 10 kg, and 15 above that. express=True doubles the base price. Any country other than "DE" then adds 10. The starter always returns 5; make every rule work.

Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.

The first run downloads Python for your browser (up to 6.5 MB) and keeps it cached. Your code stays on your device.

Hints
  1. Hint 1

    Start with an if, elif and else chain on weight that sets a variable cost.

  2. Hint 2

    Then two separate if statements: one doubles cost when express is true, one adds 10 when country != "DE".

  3. Hint 3

    The order matters: double first, then add the 10. End with return cost.

Show a solution

One way to solve it. Yours can look different and still pass the checks.

def shipping(weight, express=False, country="DE"):
    """Return the shipping cost in euros."""
    if weight <= 2:
        cost = 5
    elif weight <= 10:
        cost = 8
    else:
        cost = 15
    if express:
        cost = cost * 2
    if country != "DE":
        cost = cost + 10
    return cost


print(shipping(5, express=True, country="FR"))
Run it on your computer

Install Python 3.14 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.

main.py

def shipping(weight, express=False, country="DE"):
    """Return the shipping cost in euros."""
    return 5


print(shipping(5, express=True, country="FR"))

test_main.py

from main import shipping


def test_weights():
    """1 kg, 5 kg and 12 kg cost 5, 8 and 15"""
    got = shipping(1), shipping(5), shipping(12)
    assert got == (5, 8, 15), f"shipping(1), shipping(5) and shipping(12) returned {got!r}, expected (5, 8, 15)"


def test_boundaries():
    """2 kg costs 5 and 10 kg costs 8"""
    got = shipping(2), shipping(10)
    assert got == (5, 8), f"shipping(2) and shipping(10) returned {got!r}, expected (5, 8)"


def test_express():
    """express=True doubles the price"""
    got = shipping(1, express=True)
    assert got == 10, f"shipping(1, express=True) returned {got!r}, expected 10"


def test_abroad():
    """Another country adds 10, also by keyword in any order"""
    got = shipping(5, country="AT"), shipping(country="AT", weight=1)
    assert got == (18, 15), f"shipping(5, country='AT') and shipping(country='AT', weight=1) returned {got!r}, expected (18, 15)"


def test_express_abroad():
    """Express abroad: double first, then add 10"""
    got = shipping(5, express=True, country="FR")
    assert got == 26, f"shipping(5, express=True, country='FR') returned {got!r}, expected 26"

On macOS and Linux, type python3 wherever these commands say python, as in the first lesson.

Run the program:

python main.py

Run the checks (needs learnrun.py in the same folder):

python learnrun.py test
Download learnrun.py

Common mistakes

A default before a required parameter

def greet(greeting="Hello", name):
    return greeting + ", " + name

What Python prints

SyntaxError: parameter without a default follows parameter with a default

Why, and the fix

Once a parameter has a default, every parameter after it needs one too; otherwise Python could not tell which argument goes where. Put required parameters first: def greet(name, greeting="Hello"):.

A positional argument after a keyword argument

def greet(name, greeting="Hello"):
    return greeting + ", " + name

print(greet(greeting="Hi", "Ada"))

What Python prints

SyntaxError: positional argument follows keyword argument

Why, and the fix

In a call, positional arguments come first and keyword arguments after them. Write greet("Ada", greeting="Hi"), or name both: greet(greeting="Hi", name="Ada"). Python checks this before it runs anything, so the whole file fails.

A typo in a keyword

def greet(name, greeting="Hello"):
    return greeting + ", " + name

print(greet("Ada", greting="Hi"))

What Python prints

TypeError: greet() got an unexpected keyword argument 'greting'

Why, and the fix

A keyword must match a parameter name exactly. Python 3.14 adds a suggestion to the message, here Did you mean 'greeting'?. Correct the spelling in the call.

Python in the browser: Pyodide 314.0.7, MPL-2.0. Licence and source

Exit ticket

5 questions, no hints. Score 80% or more to complete the lesson.

Finish every activity above to unlock the exit ticket.

Report a problem

Spotted something wrong or unclear? Say what, and it will be checked and fixed.

#

At least 20 characters.

Only if you want a reply.

Key ideas

Default values make arguments optional

def greet(name, greeting="Hello"): gives greeting a default. greet("Ada") uses "Hello", and greet("Ada", "Hi") overrides it. Parameters with a default must come after those without: def greet(greeting="Hello", name): is a SyntaxError. The default is evaluated once, when the def runs, not at each call. That is harmless for numbers and strings, but a list as a default is shared between calls; lesson B4.6 shows that trap and its fix.

Keyword arguments name the parameter

A call can name the parameter: greet(name="Ada", greeting="Hi"). Named arguments can come in any order, and they work for required parameters too. They make calls readable, as in coffee_price(oat_milk=True), and let you skip earlier defaults to set a later one. Positional arguments come first: greet("Ada", greeting="Hi") is fine, but greet(greeting="Hi", "Ada") is a SyntaxError, and Python refuses to run the file.

Reading argument errors

Python checks every call against the def and names the problem. missing 1 required positional argument: a parameter without a default got no value. got multiple values for argument: the same parameter was filled by position and again by name. got an unexpected keyword argument: no parameter has that name, often a typo, and Python suggests the closest name. positional argument follows keyword argument: reorder the call so positional arguments come first.

Sources

Last reviewed September 29, 2026