Unit 06 · lesson

Parameters, Arguments, and Return Values

Core path: 30 minutes

How can one function work with different data instead of repeating the same fixed behavior?

Our first functions mostly behaved the same every time they were called.

def greet():
    print("Hello, developer.")

Useful, but limited.

Functions become much more powerful when the caller can provide data.

A parameter creates a named input boundary

def greet(name):
    print(f"Hello, {name}.")

Inside the function definition, name is a parameter.

It is a local name that will receive a value when the function is called.

Now:

greet("Maya")
greet("Jordan")

uses the same behavior with different arguments.

Trace the first call:

caller has value "Maya"

greet("Maya")

parameter name refers to "Maya"

function body uses name

prints "Hello, Maya."

The argument is the value supplied by the caller.

The parameter is the name used inside the function to receive it.

Position matters unless you say otherwise

def show_score(player_name, score):
    print(f"{player_name}: {score} points")

This call matches the parameter order:

show_score("Nova", 850)

This one is valid Python too:

show_score(850, "Nova")

But now the values are bound differently:

player_name = 850
score = "Nova"

and the output becomes nonsense for the intended meaning.

That is an important theme in programming: syntax can be valid while the data is semantically wrong.

Keyword arguments can make the mapping explicit

Python also supports:

show_score(player_name="Nova", score=850)

Now the argument-to-parameter relationship is named directly.

You do not need to convert every call into keyword arguments. Use them when they improve clarity, especially when several parameters have similar-looking values.

return sends a value back to the caller

Consider:

def calculate_damage(base, multiplier):
    damage = base * multiplier
    return damage

Then:

result = calculate_damage(50, 2)
print(result)

The call does more than execute a block. It produces a value that the caller can store or use.

Conceptually:

caller supplies arguments

parameters receive values

function calculates

return sends result back

caller receives returned value
Python value lab

Change the arguments. Follow the returned value.

The execution path stays the same, but the data moving through each stage changes with the arguments you supply.

Change base and multiplier. Before reading the result, predict the returned value and trace where each number appears inside the function.

Change the values and watch the code, trace, and model update together.

Current code
def calculate_damage(base, multiplier):
    damage = base * multiplier
    return damage

result = calculate_damage(50, 2)
print(result)
Observed result
100
  1. arguments: 50, 2
  2. parameters: base = 50, multiplier = 2
  3. damage = 50 × 2 = 100
  4. return 100 → result

Current model for base = 50, multiplier = 2. Active connections show the path or transfer currently being demonstrated.

Drag nodes to inspect the relationships. Motion shows the active path; the plain background keeps attention on the relationships instead of graph-paper decoration.

View static diagramStatic function return value pipeline

Change the live base and multiplier values.

Watch the labels update through the fixed pipeline.

Unlike the Week 4 branch model, the path itself does not change here. The data moving through the path changes.

Now execute the same boundary in a smaller runnable example:

function_return.py
OutputRun with button or Ctrl/Cmd+Enter
Run the code to see output.
Ready to edit. Press Run when you want evidence.

Change the return expression and observe how the caller receives a value from the function.

Change one argument and then change the return expression. The caller should only observe the value that crosses the function boundary, not the function's internal local names.

This function displays a value:

def add_numbers(a, b):
    print(a + b)

Then:

result = add_numbers(10, 5)
print(result)

produces something like:

15
None

The function displayed 15, but it did not return 15.

Without an explicit useful return value, Python functions return None.

Now compare:

def add_numbers(a, b):
    return a + b

The caller can decide what happens next:

result = add_numbers(10, 5)
print(result)

or:

if add_numbers(10, 5) > 12:
    print("Large result")

or:

final = add_numbers(10, 5) * 2

Returning a value makes the function composable.

A returned value can feed another function

def calculate_average(score1, score2, score3):
    return (score1 + score2 + score3) / 3


def determine_status(average):
    if average >= 70:
        return "PASS"
    return "REVIEW"

Then:

average = calculate_average(80, 90, 100)
status = determine_status(average)
print(status)

Data flows through two function boundaries:

scores

calculate_average()
  ↓ returned average
determine_status()
  ↓ returned label
print()

The functions do not have to know everything about each other. They agree on the values crossing the boundary.

return also ends the function call

Consider:

def classify(score):
    if score >= 90:
        return "A"

    return "OTHER"
    print("This never runs")

Once Python executes return, control leaves that function immediately.

Any later statement on that execution path is unreachable.

This makes early-return patterns possible later, but it also means misplaced code after return can silently become dead code.

Trace one function call precisely

def calculate_total(price, quantity):
    subtotal = price * quantity
    tax = subtotal * 0.06
    return subtotal + tax

amount = calculate_total(10.0, 3)
print(amount)

Trace:

price = 10.0
quantity = 3
subtotal = 30.0
tax = 1.8
return 31.8
amount = 31.8

Then change quantity to 5 and predict every changing value before running.

Before Lesson 3

You should be able to distinguish:

argument      value supplied by caller
parameter     local name receiving that value
local variable name created inside function
return value  data sent back to caller
printed output visible side effect

Those differences are what let functions become clean boundaries instead of little code containers.

Vocabulary lab

Flip the idea, not just the card

Explain the term before you reveal the back. Then compare your explanation with the definition, example, and warning.

1 / 5
Read all terms without animation
Parameter
A local name in a function definition that receives an argument value when the function is called. Example: name in def greet(name): Do not confuse it with: The argument supplied by the caller.
Argument
A value or expression supplied to a function call. Example: 'Maya' in greet('Maya'). Do not confuse it with: The parameter name inside the function definition.
Return Value
A value a function sends back to its caller using return. Example: return base * multiplier sends the calculated result back. Do not confuse it with: Text printed to the terminal as a side effect.
None
Python's special value commonly returned when a function finishes without returning another explicit value. Example: A function that only print()s usually returns None. Do not confuse it with: An empty string or the number zero.
Function Composition
Using the returned result of one function as input to another part of the program or another function. Example: determine_status(calculate_average(...)). Do not confuse it with: Copying the implementation of one function inside another.