DSM
60 XP
30 minsBeginner60 XP

Defining & Calling Functions

You've already USED dozens of functions — print(), len(), type(), round() — without writing one. Each is a named machine: data goes in, work happens, a result comes out. Today you build your own machines, and your code stops being a script and starts being a toolbox.

What you'll learn

  • Define functions with def and call them by name
  • Explain what happens when a call runs (jump in, execute, jump back)
  • Write docstrings that state what a function does
  • Break a script into small single-purpose functions
  • Recognize definition time vs call time

What

A function is a named, reusable block of code defined with def. You call it by name with parentheses, optionally passing inputs, and it hands control back when it finishes — usually with a result via return (which the next lesson covers in depth).

Why

Copy-pasted logic drifts: fix a bug in one copy and the other three keep it. Functions give logic ONE home — one place to fix, test, and name. Every serious codebase, from pandas to your future pipelines, is functions calling functions.

Where it's used

Every data pipeline stage (load, clean, transform, report), every test, every library API you'll call — read_csv, fit, predict are all just functions someone defined.

Where this runs in production

SpotifyFeature pipelines as functions

Audio-feature extraction is a chain of named functions — normalize_loudness, compute_tempo — each testable alone, composed into the pipeline that scores every uploaded track.

Two SigmaResearch code review

Quant researchers must ship strategies as small pure functions — pricing, signal, risk — because reviewers reject thousand-line scripts nobody can audit.

InstacartShared cleaning utilities

One clean_product_name() function is imported by dozens of internal jobs — a single fix to its logic corrected months of subtle catalog duplicates everywhere at once.

Theory

The core ideas, in plain language.

A definition starts with def, then the function's name, parentheses (holding parameter names, if any), and a colon. The indented block is the body. Defining a function runs NONE of its code — it just teaches Python the name. The body runs only when you CALL the function with name().
def greet(name):
    print(f'Hello, {name}!')

greet('Ada')
greet('Grace')

One definition, two calls. Each call jumps into the body with name bound to the argument, runs it, and jumps back. The parentheses in a call are not optional — greet alone is the function itself (a value!), greet('Ada') runs it.

Analogy: The recipe card

Writing a recipe card doesn't cook anything — it records the steps once. Cooking happens when someone follows the card, and the same card can be followed a hundred times with different ingredients. def writes the card; the call cooks. And like a good recipe card, the name on top ('Weeknight Curry') should say what you get.

Key Concept
One function, one job

The most reliable design rule in programming: a function should do ONE thing, stated by its name. load_csv() loads. remove_duplicates() removes. If the honest name would be load_and_clean_and_plot(), that's three functions being held hostage. Small single-purpose functions are testable, reusable, and — crucially — readable as a table of contents for your logic.

def celsius_to_fahrenheit(c):
    """Convert a Celsius temperature to Fahrenheit."""
    return c * 9 / 5 + 32

print(celsius_to_fahrenheit(100))  # 212.0

The triple-quoted string right under the def is a docstring — the function's built-in documentation, shown by help() and your editor's hover. One clear sentence is enough. return sends the result back to the caller; the full story of parameters and return is next lesson.

Naming: functions are actions, so name them verb-first in snake_case — calculate_tax, validate_email, fetch_orders. The name is the function's contract with every future reader; a good one makes the docstring almost redundant, a bad one (process, do_stuff, helper2) makes every call site a mystery.
Watch out
Calling vs referencing

greet('Ada') calls the function. greet without parentheses is a REFERENCE to it — a value you can store or pass around (that's how higher-order functions will work later this module). The classic bug: writing result = get_total instead of result = get_total(), then wondering why result is '<function get_total at 0x...>' instead of a number.

Visual Learning

See the concept, then explore it.

What happens during a function call

Execution jumps into the body and back. Click each stage to follow the control flow.

Worked Examples

Watch it built up, one line at a time.

Very EasyDefine, then call

A reusable banner printer for a report script.

Step 1 of 2

A function with no parameters — the parentheses are empty but still required. Defining it prints nothing.

Code
01def print_banner():
02 print('=' * 30)
03 print(' DAILY SALES REPORT')
04 print('=' * 30)
Practice Coding

Your turn — write the code.

Your task

Build a tiny discount toolkit. Define apply_discount(price, pct) returning the discounted price rounded to 2 decimals, and format_price(amount) returning a '$xx.xx' string. Then use both to print the final price of a $80.00 item at 15% off.

Expected output
$68.00

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

What does defining a function with def actually execute?

After `def get_rate(): return 0.08`, what does `x = get_rate` (no parentheses) make x?

Medium0/3 solved

Which function name best follows the one-job rule and naming conventions?

ScenarioA teammate's function prints its result: `def tax(amount): print(amount * 0.2)`. Your pipeline needs to ADD that tax to a subtotal, but total = subtotal + tax(80) crashes with a TypeError about NoneType.

Why, and what's the fix?

Define count_longer_than(words, n) that returns how many strings in words have more than n characters. Then print count_longer_than(['data', 'ai', 'python', 'ml'], 3). Expected output: 2

Returns, not prints:The function must return the count; only the caller prints
Correct count:'data' (4) and 'python' (6) exceed 3 → 2
Hard0/2 solved

A script calls report() on line 5, and defines `def report(): ...` on line 20. What happens when the script runs?

Build a two-function pipeline: to_floats(strings) converts a list of numeric strings to floats; total(values) returns their sum. Compose them to print the total of ['12.5', '7.25', '30.0']. Expected output: 49.75

Two single-purpose functions:Conversion and summation live in separate named functions
Composition:One function's return value feeds the other: total(to_floats(raw))
Complete 80% more exercises to unlock.
Interview Prep

How this shows up in real interviews.

Why do functions matter for code quality? Name the concrete benefits.

Show model answer

Four concrete wins. Reuse: logic written once is called everywhere, so a fix lands everywhere at once instead of drifting across copies. Testability: a small function with inputs and a return value can be verified in isolation with three lines of test data — a 400-line script cannot. Readability: well-named functions turn a script into a table of contents; readers grasp the flow without reading every body. Abstraction: callers depend on the NAME and contract, not the implementation, so you can rewrite the inside (faster algorithm, different library) without touching call sites. The underlying principle is single responsibility — one function, one job — because everything above follows from it.

What's the difference between definition time and call time, and what bug class does the distinction explain?

Show model answer

def executes when Python reads it: it builds the function object and binds the name — but never runs the body. The body runs at call time, freshly, for every call. This explains two bug classes. First, NameErrors from calling above the definition in a script — at that line, the name doesn't exist yet. Second, and more important: broken bodies that hide. A function whose body would crash — a typo'd variable, a bad conversion — defines without complaint and detonates only on first call, possibly weeks later in production on the one input path nobody exercised. That's precisely why untested code paths are treated as unshipped code on mature teams.

print() versus return — explain the difference and when each is appropriate.

Show model answer

return hands a value back to the caller, making the call expression stand for that value — it can be stored, compared, summed, or passed onward; that's what makes functions composable. print() writes text to the screen for a human and returns None; the 'result' is unrecoverable by code. So: computation functions should return, and the caller — usually at the program's edge — decides what to print. A function that prints instead of returning poisons composition: subtotal + tax(80) becomes number + None and crashes. The habit to state in interviews: return for programs, print for people, and keep printing at the outermost layer.

Common Mistakes to Avoid

1) Printing inside a function when the caller needs the value — return it instead. 2) Forgetting parentheses: get_total is the function, get_total() is its result. 3) Calling a function above its def in a script — NameError. 4) One mega-function doing five jobs — if the name needs 'and', split it. 5) Vague names (process, handle, do_it) that force readers into the body. 6) Assuming a clean definition means working code — bodies only fail at call time, so call it (test it) before trusting it.

Ask the AI Tutor

Try these prompts in the AI Tutor panel: • 'Show me a 20-line script and help me split it into functions.' • 'Quiz me: which of these five defs runs code at definition time?' • 'Critique these function names and suggest better ones.' • 'Show the print-instead-of-return bug and its stack trace.' • 'Interview mode: ask me why small functions beat big ones and grade my answer.'

Glossary

Function — a named, reusable block of code run by calling it. def — the keyword that defines a function. Call — executing a function with name(arguments). Parameter — the placeholder name in the definition. Argument — the actual value passed in a call. Body — the indented block that runs at call time. Docstring — the triple-quoted description right under the def. return — statement sending a value back to the caller. Definition time — when def executes (binds the name). Call time — when the body actually runs. Composition — feeding one function's return value into another.

Recommended Resources

• Docs: 'Defining Functions' in the official Python tutorial. • Read: PEP 257 (docstring conventions) — two minutes, lifelong habit. • Practice: take your longest script from earlier lessons and refactor it into three named functions with a three-line main section. • Next in DSM: parameters deserve their own lesson — Parameters, Arguments & Return Values covers multiple inputs, multiple returns, None, and the contracts that make functions trustworthy.

Recap

✓ def names a block; calling name() runs it — definition time records, call time executes. ✓ Parameters receive arguments; each call is a fresh, independent run. ✓ return hands values back for further computation; print is only for humans. ✓ One function, one job, verb-first snake_case name, one-line docstring. ✓ Functions calling functions turn scripts into readable, testable pipelines. ✓ A function reference without () is a value — useful later, a classic bug today. Next up: Parameters, Arguments & Return Values. You can define and call — now master what flows in and out: multiple parameters, multiple returns, None, and early returns.

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

Run your code to see the output here.