Lesson 7 of 915 min2 challenges

Functions: Packaging a Skill

return and print are two different jobs, and variables born inside a function stay there.

Packaging a skill

Write the same logic in three places and you now have three places to fix when it changes. You will fix two of them and ship the bug in the third. That's not carelessness — it's arithmetic.

A function is a box with a name. Put the logic in once, say the name whenever you need it.

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

greet("Maya")
greet("Ben")

Output:

Hello, Maya!
Hello, Ben!

Taking it apart:

  • def — tells Python "a function definition starts here."
  • greet — the name. Same naming rules as variables.
  • (name) — the parameter: a name for the material that gets handed in when the function is called.
  • The colon and the indented block — same grammar as if and for. The indented lines are the function's body.

Defining is not running. When Python reaches the def block, it reads it, remembers it, and runs none of it. The body executes only when something calls greet(...). This is why a file full of function definitions and no calls produces no output at all, which puzzles people the first time.

return: handing a result back

print shows something to a human. return hands a value back to the code that made the call. These are completely different jobs, and confusing them is the number one function bug.

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

result = add(3, 5)
print(result)
print(add(1, 2) * 10)

Output:

8
30

Because add returns a value, add(1, 2) behaves like the number 3 right where it sits, so you can multiply it. Values that come back can keep being used.

Now the version that looks the same and isn't:

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

result = add(3, 5)
print(result)

Output:

8
None

The 8 appears because of the print inside the function. Then result is None, because a function with no return hands back None. None is Python's word for "nothing here." It's a real value, and you'll see it whenever you capture the result of a function that only printed.

The test to apply: does the caller need to use the answer? Then return it. Printing inside the function throws the value away after showing it once.

return also ends the function immediately:

def check(age):
    if age < 0:
        return "Age can't be negative"
    return "Looks fine"

print(check(-5))
print(check(30))

Output:

Age can't be negative
Looks fine

No else needed — when the first return runs, the rest of the function never happens. Handling bad input at the top and leaving early is called a guard clause. It saves you several levels of nesting and keeps the normal path unindented at the bottom, where it's easy to read.

Ways to pass arguments

def power(base, exp=2):
    return base ** exp

print(power(3))
print(power(3, 3))
print(power(exp=3, base=2))

Output:

9
27
8

exp=2 is a default value: leave the argument out and 2 is used. This lets one function serve the common case with less typing while still allowing the unusual one.

The third call passes arguments by name, which means order stops mattering and the call documents itself. For a function with several options, naming them is kinder to whoever reads it later.

One rule: parameters with defaults must come after parameters without them. def f(a=1, b) is a syntax error, because Python would have no way to tell which value you meant.

Scope: what happens inside stays inside

def f():
    x = 10
    print(x)

f()
print(x)

Output:

10
NameError: name 'x' is not defined

The function body is a separate room. Variables created in there vanish when the function ends.

That's a feature, not a limitation. It means you can name a variable total inside a function without checking whether some other part of the program already uses total. The door out is return.

The same isolation explains this:

def bump(x):
    x = x + 1

a = 5
bump(a)
print(a)

Output:

5

bump received a copy of the value and renamed it x inside its own room. Changing x there does nothing to a out here, and nothing was returned. If you want the new value, return it and catch it: a = bump(a).

Three rules for writing good ones

  1. One function, one job. If the name needs an "and" in it, that's two functions.
  2. Name it with a verb. calculate_total, is_valid, load_data. A reader should know what it does without opening it. Functions that return True or False read well starting with is_ or has_.
  3. Arguments in, value out. A function that depends only on what's handed to it can be tested on its own, reused anywhere, and understood without reading the rest of the program.

Leave a note

def bmi(weight, height):
    """Calculate BMI. weight in kilograms, height in meters."""
    return weight / (height ** 2)

print(f"{bmi(70, 1.75):.1f}")

Output:

22.9

The triple-quoted line right under def is a docstring. One sentence saying what the function does and what units the arguments use is enough. Tools display it, and your future self stops guessing whether height was meant in meters or centimeters.

Ten-second check

def f(x):
    x = x + 1

a = 5
f(a)
print(a)

The answer is 5. The function modified its own local copy and returned nothing, so the outside world never heard about it. If you expected 6, you were picturing the function reaching out and editing a directly. It can't, and that's exactly what makes functions safe to use.

Ad slot (AdSense not configured; ads appear here in production)

Hands-on

Reading it isn't knowing it. Writing it is.

0/2 passed

Challenges and grading are completely free, and a wrong answer costs you nothing. Stuck? Hit "Ask the AI": it can see the code you are writing.

Level 01Multiple choice+10 pts · +15 XP

What Comes Back Without a return

```python def add(a, b): print(a + b) result = add(1, 2) ``` What is the value of `result`?

  • Might be multiple choice. Wrong answers cost nothing, so just try.
Level 02Write code+20 pts · +30 XP

Write a Leap Year Function

Finish `is_leap(year)` so it returns True for a leap year and False otherwise. The rule: divisible by 4 and not by 100, **or** divisible by 400.

Sample input

(none)

Expected output

True
False
True
False
pythonTab = 4 spaces

Finished? Mark it

Marking it done saves your progress, gives you 20 XP and keeps your streak alive.