DSM
60 XP
30 minsBeginner60 XP

Parameters, Arguments & Return Values

A function is a contract: give me THESE inputs, get back THIS output. Fuzzy contracts cause the bugs that eat afternoons — wrong argument order, forgotten returns, a None where a number should be. This lesson makes you precise about both sides of the arrow.

What you'll learn

  • Match positional arguments to parameters correctly
  • Return multiple values with tuples and unpack them
  • Handle functions that return None — deliberately or accidentally
  • Use early returns to simplify branching logic
  • Trace what a call expression evaluates to

What

Parameters are the names a function declares; arguments are the values a caller supplies, matched by position. return ends the call and delivers a value — or several, or None if you don't return at all.

Why

Data pipelines are functions wired output-to-input. One function quietly returning None, or arguments passed in the wrong order, breaks the chain in ways that surface far from the cause. Understanding the contract is understanding where pipelines break.

Where it's used

Every function you write or call: sklearn's fit(X, y) argument order, functions returning (train, test) pairs, validators returning a value or None.

Where this runs in production

scikit-learntrain_test_split's multiple returns

The most-called line in ML — X_train, X_test, y_train, y_test = train_test_split(X, y) — is a function returning four values as a tuple, unpacked in one assignment.

SlackValidators returning value-or-None

Message-parsing functions return the parsed object or None; callers write `if parsed:` — the value-or-None contract keeps malformed input from crashing channels.

ToyotaSensor calibration chains

Factory calibration software chains conversion functions, each output feeding the next input — one function's misordered arguments would mis-calibrate a production line.

Theory

The core ideas, in plain language.

By default, arguments match parameters by POSITION: the first argument lands in the first parameter, second in second. def net_price(gross, discount) called as net_price(100, 0.2) binds gross=100, discount=0.2. Swap the arguments and Python won't complain — you just get a silently wrong answer. Position is meaning.
Analogy: The airport check-in form

A paper form has labeled boxes in fixed positions: surname first, then given name. Fill them in the wrong order and the airline happily prints a boarding pass for 'Ada Lovelace' reversed — the SYSTEM accepted it; the MEANING broke. Positional arguments are those boxes: the function trusts you filled them in declaration order.

def describe(value, decimals):
    return f'{round(value, decimals)}'

print(describe(3.14159, 2))  # 3.14  — correct order
print(describe(2, 3.14159))  # 2     — legal, meaningless

Both calls run. Only one is right. When a function grows past two or three parameters, this fragility is why keyword arguments exist — next lesson's topic.

Key Concept
return ends the call — immediately

return does two jobs at once: it delivers a value AND terminates the function on the spot. Any code after an executed return never runs. That's not a limitation — it's the tool: 'early returns' handle edge cases at the top (return the answer for the easy case now) so the main logic below stays flat. You met this shape as guard clauses; return is what powers them.

def safe_average(values):
    if len(values) == 0:
        return 0.0
    return sum(values) / len(values)

print(safe_average([10, 20, 30]))  # 20.0
print(safe_average([]))            # 0.0 — no crash

Two returns, one function: the guard exits early for the empty case (preventing a division by zero), and the main return handles real data. Multiple return statements are normal, healthy Python.

To return several values, return them separated by commas — Python packs them into a tuple — and unpack at the call site with matching names: `low, high = min_max(data)`. This is the idiom behind train_test_split's four-way return, and you've already used its cousin in for day, temp in enumerate(temps).
Watch out
Arity errors and silent swaps

Passing the wrong NUMBER of arguments fails loudly: 'missing 1 required positional argument' or 'takes 2 but 3 were given' — read these carefully, they name the function and count. Passing the wrong ORDER with compatible types fails silently — no error, wrong result. Loud failures cost minutes; silent ones cost afternoons. Defend with clear parameter names, few parameters, and (next lesson) keyword arguments.

Visual Learning

See the concept, then explore it.

The call contract: in by position, out by return

split_bill(96.0, 3) from both sides of the arrow. Click each stage.

Worked Examples

Watch it built up, one line at a time.

Very EasyTwo parameters, one return

Compute the price per unit for a bulk purchase.

Step 1 of 2

Two positional parameters. The function's whole job fits in the return line.

Code
01def unit_price(total_cost, units):
02 return total_cost / units
Practice Coding

Your turn — write the code.

Your task

Write grade_stats(scores) that returns THREE values: the average (rounded to 1 decimal), the highest score, and how many scores passed (60+). Guard the empty-list case by returning (0.0, 0, 0). Unpack and print the results for the class list provided.

Expected output
Average: 69.7
Top: 91
Passed: 4

Write your solution in the editor on the right, then hit Run.

Exercises

Prove it. Reach 80% to complete the lesson.

Mastery Gate0% / 80% required
Easy0/2 solved

def area(width, height): return width * height — what does area(3, 4) bind?

What does a function return if execution reaches the end of its body without any return statement?

Medium0/3 solved

def stats(xs): return min(xs), max(xs) — what TYPE does stats([3, 1, 4]) evaluate to?

ScenarioA lookup function returns a discount percentage, or None for customers with no discount. A teammate writes: `if get_discount(cust):` to test whether a discount exists — and customers with a legitimate 0% promotional discount are treated as having none.

What's the correct test?

Write bmi(weight_kg, height_m) returning the BMI rounded to 1 decimal (weight / height²). Print bmi(70.0, 1.75). Expected output: 22.9

Parameter order:weight first, height second — matching the call
Returns the value:The function returns; printing happens at the call site
Hard0/2 solved

def check(n): if n > 10: return 'big' print('small') What does `result = check(3)` leave in result?

Write classify_temp(celsius) using early returns: return 'invalid' if celsius is None, 'freezing' below 0, 'cold' below 15, 'warm' below 28, else 'hot'. Print the results for None, -4, 22, 31 (one per line). Expected: invalid freezing warm hot

Guard first:The None check must come before any numeric comparison
No elif/else needed:Each return exits, so plain ifs suffice — flat, not nested
Complete 80% more exercises to unlock.
Interview Prep

How this shows up in real interviews.

What's the difference between a parameter and an argument?

Show model answer

A parameter is the name declared in the function definition — the labeled empty box. An argument is the actual value a caller supplies — what goes into the box, matched by position by default. The distinction sounds pedantic but pays off when reading error messages: 'missing 1 required positional argument: height' names the PARAMETER that no ARGUMENT filled, telling you exactly which box is empty. It also frames the deeper point that the function body only ever sees its parameter names — callers and callees are decoupled, communicating purely through the ordered handoff of values.

How does Python return multiple values, and what's actually happening under the hood?

Show model answer

return a, b, c packs the values into a single tuple — the function still returns exactly one object. The multi-value feel comes from unpacking at the call site: lo, hi, span = value_range(data) assigns the tuple's elements to three names, and raises a loud ValueError if the counts mismatch. This is the idiom behind sklearn's train_test_split returning four arrays. Two design cautions worth volunteering: keep the element order meaningful and documented (callers must remember it), and past three or four values, return something with named fields instead — a dict or a small class — because positional unpacking of six anonymous values is a bug factory.

Describe the 'return value or None' contract — its uses and its hazards.

Show model answer

The contract: a function returns the meaningful result when it can, and None when it can't — parse_price returns a float or None, a lookup returns the record or None. It keeps expected failures (malformed input, missing keys) from becoming exceptions, letting callers handle them with a simple test. Two hazards. First, the truthiness trap: `if result:` wrongly treats legitimate falsy results — 0, empty string, empty list — as failures; the correct test is `is not None`. Second, None is contagious: if a caller forgets to check, the None flows onward and detonates later as a confusing TypeError far from its source. Teams mitigate with docstrings that state the contract, `is not None` discipline, and — in typed codebases — Optional annotations so the checker forces the question.

Common Mistakes to Avoid

1) Computing a result and forgetting the return line — caller gets None. 2) Swapping compatible-typed arguments: no error, wrong answer; keep parameter lists short and meaningful. 3) Testing a value-or-None result with truthiness when 0 or '' are legitimate — use `is not None`. 4) Code placed after a return in the same branch — unreachable. 5) Unpacking the wrong number of values — count both sides. 6) Believing print inside the function 'returned' something; the caller still received None.

Ask the AI Tutor

Try these prompts in the AI Tutor panel: • 'Quiz me: what does each of these five calls evaluate to?' • 'Show a silent argument-swap bug in a real-looking function.' • 'Refactor this nested if/else into early returns with me.' • 'Explain the value-or-None contract with a new example.' • 'Interview mode: ask me about multiple return values and grade my answer.'

Glossary

Parameter — the name declared in a def's parentheses. Argument — the value supplied at the call. Positional matching — first argument to first parameter, by order. return — statement that ends the call and delivers a value. Early return — exiting at the top for edge cases (guard clauses). Tuple packing — return a, b bundles values into one tuple. Unpacking — lo, hi = f() splits a returned tuple into names. None — the value of a function that returns nothing. Arity — the number of arguments a function expects. Value-or-None contract — return the result, or None for expected failure.

Recommended Resources

• Docs: 'More on Defining Functions' in the official Python tutorial. • Read: the train_test_split docs — spot the four-way tuple return and the parameter order you now understand. • Practice: write min_max_mean(values) returning three values with an empty-list guard, and unpack it three different ways. • Next in DSM: positional order is fragile past two parameters — Default & Keyword Arguments lets callers name what they pass and lets functions ship sensible defaults.

Recap

✓ Arguments fill parameters by position; order is meaning, and silent swaps are the danger. ✓ return delivers a value AND exits immediately — early returns keep logic flat. ✓ return a, b, c packs a tuple; unpack with matching names at the call site. ✓ No return means None — sometimes a contract, often a bug. ✓ Test value-or-None results with `is not None`, never bare truthiness, when falsy values are legitimate. ✓ Loud arity errors beat silent order errors — design parameter lists to fail loud. Next up: Default & Keyword Arguments. Callers shouldn't have to pass everything every time — defaults give parameters fallback values, and keywords let calls name their intent.

scratchpad — preview this lesson's challenge anytime
grades.pyPython
Ready
Output

Run your code to see the output here.