Skip to content

Functions and Modules

💡
Before you start

You need Python installed, and to know how to run a .py file. If python3 --version in a terminal prints a version number, you are ready. If it does not — or if you have never opened a terminal — do Getting Started with Python first; it installs Python and runs your first program, and takes about fifteen minutes. Nothing else is needed: no account, no payment, no extra software.

What Are Functions?

A function is a reusable block of code that performs a specific task. Instead of writing the same code over and over, you write it once as a function and call it whenever you need it.

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

greet("Alice")      # Hello, Alice!
greet("Bob")        # Hello, Bob!
💡
Why use functions?

Functions make your code organized, reusable, and easier to debug. If something breaks, you only need to fix it in one place instead of everywhere you copied the code.

Defining Functions

Use the def keyword to create a function:

def function_name(parameter1, parameter2):
    """Optional description of what the function does."""
    # Code goes here
    return result

Key parts:

  • def — keyword that starts a function definition
  • function_name — use lowercase with underscores (snake_case)
  • parameters — input values the function receives (optional)
  • return — sends a value back to the caller (optional)

Parameters and Arguments

Parameters are the variables listed in the function definition. Arguments are the actual values you pass when calling the function:

def add(a, b):          # a and b are parameters
    return a + b

result = add(5, 3)     # 5 and 3 are arguments
print(result)          # 8

Default Parameters

Give parameters default values so they're optional:

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

greet("Alice")               # Hello, Alice!
greet("Bob", "Good morning") # Good morning, Bob!

Keyword Arguments

You can specify arguments by name for clarity:

def create_user(name, age, role="user"):
    print(f"{name}, age {age}, role: {role}")

create_user("Alice", 30)
create_user(name="Bob", role="admin", age=25)

Return Values

Functions can send values back using return:

def square(n):
    return n * n

result = square(5)
print(result)           # 25

# You can return multiple values
def divide(a, b):
    quotient = a // b
    remainder = a % b
    return quotient, remainder

q, r = divide(17, 5)
print(f"17 / 5 = {q} remainder {r}")    # 17 / 5 = 3 remainder 2
⚠️
Return vs Print

return sends a value back to the code that called the function. print() just displays text on screen. If you need to use a function's result later, you must return it, not print it.

Variable Scope

Variables created inside a function only exist within that function:

def my_function():
    local_var = "I'm local"
    print(local_var)

my_function()           # Works fine
# print(local_var)      # Error! local_var doesn't exist here

# Global variables are accessible everywhere
global_var = "I'm global"

def another_function():
    print(global_var)   # Can read global variables

another_function()      # I'm global

Practical Function Examples

# Temperature converter
def celsius_to_fahrenheit(celsius):
    return (celsius * 9/5) + 32

print(celsius_to_fahrenheit(0))     # 32.0
print(celsius_to_fahrenheit(100))   # 212.0

# Password strength checker
def check_password(password):
    if len(password) < 8:
        return "Weak: too short"
    if password.isalpha():
        return "Medium: add numbers"
    if password.isalnum():
        return "Good: add special characters"
    return "Strong"

print(check_password("abc"))         # Weak: too short
print(check_password("abcdefgh"))    # Medium: add numbers
print(check_password("abc12345"))    # Good: add special characters
print(check_password("abc123!@"))    # Strong

Modules and Imports

Modules are Python files containing functions and variables that you can reuse. Python comes with hundreds of built-in modules.

Importing Modules

# Import the entire module
import math
print(math.sqrt(16))     # 4.0
print(math.pi)           # 3.141592653589793

# Import specific functions
from random import randint, choice
print(randint(1, 10))         # Random number between 1-10
print(choice(["a", "b"]))    # Random pick from list

# Import with alias
import datetime as dt
today = dt.date.today()
print(today)                  # 2026-03-04

Useful Built-in Modules

  • math — Mathematical functions (sqrt, pi, ceil, floor)
  • random — Random number generation (randint, choice, shuffle)
  • datetime — Date and time handling
  • os — Operating system interaction (files, paths, env vars)
  • json — Read and write JSON data
  • sys — System-specific parameters (argv, exit)

Creating Your Own Module

Any Python file can be imported as a module:

1
Create helpers.py:
def greet(name):
    return f"Hello, {name}!"

def add(a, b):
    return a + b
2
Use it in another file (main.py):
import helpers

print(helpers.greet("Alice"))   # Hello, Alice!
print(helpers.add(5, 3))        # 8

Now Do It Yourself: Five Steps

A function is a named piece of work you can run whenever you want, with different inputs each time. You will write one, give it options, and use it twice. Every output below is exactly what Python printed.

1
Write your first function and call it twice

Go: open a terminal, run cd ~, and create a file called funcs.py.

Do: type these four lines and run python3 funcs.py.

def greet(name):
    return "Hello, " + name + "!"

print(greet("Alice"))
print(greet("Bob"))

You should see: Hello, Alice! then Hello, Bob!. Writing def only defines the function — nothing happens until something calls it, which is what the two print lines do.

If not: if nothing prints at all, you have only the def block and no call. If you see IndentationError, the return line needs four spaces in front of it; everything belonging to the function is indented under the def.

2
Learn the difference between printing and returning

Go: same file, replace the contents.

Do: type these four lines and run it. This one is supposed to look wrong.

def add(a, b):
    a + b

print(add(2, 3))

You should see: None. The function did the addition and then threw the answer away, because there is no return. None is Python's word for "no value", and it is what every function hands back when you do not tell it otherwise.

If not: if you see 5, you already added return — take it out and look at None once, deliberately. Recognising it instantly saves real time later: None almost always means "a function forgot to return something".

3
Fix it, and see the value come back

Go: same file.

Do: add the word return in front of a + b, so the line reads return a + b, then run it again.

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

print(add(2, 3))

You should see: 5. return hands the value back to whoever called the function, which is what lets you use the result — store it, print it, or feed it into something else.

If not: TypeError: unsupported operand type(s) for +: 'int' and 'str' means one of your arguments arrived as text. add(2, "3") fails; add(2, 3) works. Functions do not convert types for you.

4
Give an argument a default, so it becomes optional

Go: same file, replace the contents.

Do: type these five lines and run it.

def greet(name, greeting="Hello"):
    return greeting + ", " + name + "!"

print(greet("Alice"))
print(greet("Alice", "Welcome"))

You should see: Hello, Alice! then Welcome, Alice!. The default is used when you leave that argument out, and overridden when you supply one. This is how you add an option to a function without breaking every existing call to it.

If not: SyntaxError: parameter without a default follows parameter with a default means you wrote them the wrong way round. Arguments with defaults must come last, because Python matches the ones without defaults by position first.

5
Meet the error you will cause most often

Go: same file.

Do: change the last two lines to a single print(greet()), with nothing inside the brackets, and run it.

You should see: TypeError: greet() missing 1 required positional argument: 'name'. Read it literally: the function needs a name and you gave it none. greeting is not mentioned, because it has a default and is therefore optional.

If not: if it prints a greeting anyway, you gave name a default too. That is legal, but it hides mistakes — only give a default to arguments that genuinely have a sensible one. Put the call back to greet("Alice") before moving on.

🎉
Check yourself before moving on

Without scrolling up: a function runs its code correctly but the caller keeps receiving None. What is missing? Answer: return. Doing the work and handing back the answer are two separate things.

Now do it without the page: write area(width, height) that returns width times height, with height defaulting to 1, and print both area(5) and area(5, 3). Same shape as step 4.

Summary

  • Functions are defined with def name(parameters):
  • return sends values back to the caller
  • Parameters can have default values for optional arguments
  • Variables inside functions are local to that function
  • Modules let you organize and reuse code across files
  • Use import to access built-in or custom modules
🎉
Functions unlocked!

You can now write organized, reusable code. Next up: lists, tuples, and dictionaries — Python's powerful data structures for managing collections of data.