At some point you'll catch yourself copying and pasting the same few lines of code for the third time, and that's usually the moment a function starts to feel less like a "nice to have" and more like something you actually need.

The basics

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

greet("Sam")

def starts a function definition, followed by a name and, in parentheses, whatever inputs it needs. Nothing shocking if you've seen functions in other languages — the main visual difference is, once again, no curly braces, just a colon and an indented block.

Returning a value

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

total = add(2, 3)
print(total)  # 5

A function that doesn't explicitly return anything hands back None by default, which is Python's way of saying "nothing here." This catches people out occasionally — you call a function expecting a value, print it, and get None, because somewhere along the way a return statement got forgotten.

Default values for parameters

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

greet("Sam")               # Hello, Sam!
greet("Sam", "Hey")        # Hey, Sam!

Giving a parameter a default value makes it optional. Callers can leave it out entirely and get sensible behaviour, or supply their own value when the default doesn't fit.

Keyword arguments

Python lets you call a function by naming its parameters directly, rather than relying purely on the order you list them, which is especially handy once a function has more than two or three parameters and you don't want to count commas to figure out which value goes where:

greet(name="Sam", greeting="Hey")
greet(greeting="Hey", name="Sam")  # order doesn't matter here

A small design tip

A function should really do one job. If you find yourself naming a function processAndSaveAndEmailUser, that's usually a hint it's doing three jobs stitched together, and splitting it into three smaller functions almost always makes the code easier to test and easier to read six months later when you've forgotten exactly how it works.

Why bother

Functions aren't just about avoiding repeated typing, although that's a nice side effect. They give a chunk of logic a name, and a good name tells the reader what is happening without them needing to read every line inside it. That's the real payoff, and it only grows as a program gets bigger.