Basic

Functions

Package reusable logic into functions with parameters, return values, and defaults.

What you will see

(1, 2) {'name': 'Ada'}

About 2 min of reading

Quick check

Before this new lesson, one small question about the lesson you just finished. Recall it, do not look it up.

Try It

A function packages logic I can reuse. I define one and call it twice, lean on a default argument so callers can skip one, return several values at once, share a number with the outside world using global, and pass a variable pile of positional and keyword values.

1

def names a function and return sends a value back. I greet two people through the same function and print what each call yields.

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

Before you run it, say out loud what it will print. Then open the answer.

What it prints
Hello, Ada! Hello, Bob!
A function with no return statement returns None. Without it the call does nothing useful for the caller.
2

Defaults let a caller omit an argument. I base it to a power, calling it once with just the base to use the default and once with both, then print both results.

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

Before you run it, say out loud what it will print. Then open the answer.

What it prints
9 1024
Defaults are evaluated once, at definition time. Fine for values like numbers, but avoid a mutable default such as a list.
3

Python packs several returns into one tuple and lets me split it on assignment. I divide a number and grab the quotient and remainder as two separate variables at once.

def divide(a, b): return a // b, a % b quotient, remainder = divide(17, 5) print(quotient, remainder)

Before you run it, say out loud what it will print. Then open the answer.

What it prints
3 2
The double return builds a tuple behind the scenes. The number of variables on the left must match what it returns.
4

A name made inside a function stays local, but global lets a function reach a value from the outside. I bump a shared counter twice and print it from the outside to confirm the change stuck.

count = 0 def increment(): global count count += 1 increment() increment() print(count)

Before you run it, say out loud what it will print. Then open the answer.

What it prints
2
Reading a global works without a declaration, but assigning to it needs the global keyword or Python treats it as a new local.
5

A function can swallow any number of extra values. args gathers positionals into a tuple and *kwargs collects keywords into a dict, so I print each container to see exactly what arrived.

def summary(*args, **kwargs): print(args) print(kwargs) summary(1, 2, name="Ada")

Before you run it, say out loud what it will print. Then open the answer.

What it prints
(1, 2) {'name': 'Ada'}
The * and ** only work in the function definition here. Passing them on a call would unpack, which is a different feature.

Put it in order

Before you write anything, put these lines back in the right order. Click a line to move it up one step. This support step is easier than writing code from scratch, and it is here to make the last example stick.

Data Flow

Arguments flow into a function, its body computes a result, and the return value flows back out.
1 Caller passes arguments -> bound to parameters
↓
2 Function body runs with local variables
↓
3 return produces a value -> handed back to caller
↓
4 Caller receives value -> continues execution
Line by line

Read the first example one line at a time. A line that prints shows what appears on screen; the rest set things up quietly.

def greet(name): sets nothing on screen
return f"Hello, {name}!" sets nothing on screen
print(greet("Ada")) Hello, Ada!
print(greet("Bob")) Hello, Bob!
Why this works
Arguments: positional, keyword, *args

Parameters can be positional, given defaults, or accept a variable number of arguments:

def summary(*args, **kwargs):
    print(args)    # tuple of positional
    print(kwargs)  # dict of keyword

summary(1, 2, name="Ada")

args collects extra positionals into a tuple; *kwargs collects keyword args into a dict.

When you have a choice

Local vs global scope

Variables assigned inside a function are local to that function. Reading a global is fine, but assigning to a global name requires the global keyword:

count = 0
def increment():
    global count
    count += 1

Prefer passing values in and returning results out rather than reaching for globals, it makes functions predictable and testable.

Examples

Defining and calling functions

Writing a function

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

print(greet("Ada"))   # Hello, Ada!

def declares a function; return sends a value back to the caller. Without return, a function returns None.

Default and keyword arguments

Flexible parameters

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

print(power(3))      # 9 (uses default)
print(power(2, 10))  # 102

Defaults let callers omit arguments. Keyword calls make order irrelevant: power(exp=3, base=2).

Multiple return values

Returning several values

def divide(a, b):
    return a // b, a % b

quotient, remainder = divide(17, 5)
print(quotient, remainder)   # 3 2

Python packs multiple returns into a tuple and unpacks them on assignment.

Words this lesson uses

Each one is defined here on this site. Open the entry for the full definition and the other words it points at.

← Loops and Iteration
Previous Lesson
Loops and Iteration
Next Lesson
Lists and Dictionaries
Lists and Dictionaries →