Functions

Learn how to write reusable blocks of code called functions to organize your programs and avoid repeating yourself.

~21 min Beginner

Write once, use many times

A function is a named block of code that does a specific job. You write it once, then you can use it, which is called calling it, as many times as you want anywhere in your program. Functions help you avoid repeating the same code, make programs easier to read, and let you break big problems into small manageable pieces.

You have already used built-in functions like print(), len(), input() and int(). Now you will learn to create your own.

Use the def keyword, then the function name, then parentheses, then a colon. The code inside must be indented:

def greet():
    print("Hello, World!")
    print("Welcome to Python.")

greet()   # call the function
greet()   # call it again
Hello, World!
Welcome to Python.
Hello, World!
Welcome to Python.

There are two steps, and they are different. Defining (def) only teaches Python the recipe. Nothing runs yet. Calling (greet()) is what actually runs the recipe. If you define a function but never call it, nothing happens. Also, a function must be defined before the line that calls it.

Parameters

Parameters are inputs you give to a function so it can do different things with different data. They are the names inside the brackets of the def line:

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

greet("Alice")    # Hello, Alice!
greet("Bob")      # Hello, Bob!
greet("Charlie")  # Hello, Charlie!

You can have multiple parameters, separated by commas:

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

add(3, 5)    # 8
add(10, 20)  # 30

A small piece of vocabulary: the names in the def line (a, b) are parameters. The real values you pass when calling (3, 5) are arguments. Arguments are matched to parameters by position, so the first argument goes into the first parameter.

You can also pass arguments by name, which makes calls easier to read and lets you change the order:

def describe(animal, sound):
    print(f"A {animal} says {sound}.")

describe(sound="moo", animal="cow")   # A cow says moo.

If you give the wrong number of arguments, Python raises a TypeError.

Return values

A function can calculate something and send the result back. Use the return keyword:

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

result = add(3, 5)
print(result)           # 8
print(add(10, 20) + 5)  # 35

When a function hits return, it stops immediately and sends the value back. Any code after the return in that function does not run.

def check(n):
    return "big"
    print("This never runs")

What is the difference between printing and returning? print only shows something on the screen. return hands the value back to the code that called the function, so you can store it or use it in more math. Most of the time you want return.

def double(n):
    return n * 2

x = double(4) + double(3)   # 8 + 6
print(x)                    # 14

A function with no return gives back None, which means "nothing". You can also return several values at once, separated by commas, and unpack them: low, high = get_range().

Default parameter values

You can give parameters default values. If the caller does not provide that argument, the default is used:

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

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

Parameters with defaults must come after the ones without. This makes functions flexible. The common case stays short, and anyone who needs something different can override it.

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

print(power(3))      # 9, uses the default exponent 2
print(power(3, 3))   # 27

Many built-in functions work this way. For example, print() ends with a new line by default, and round(x) rounds to a whole number unless you give a second argument.

Variable scope

Variables created inside a function only exist inside that function. They cannot be accessed from outside. This is called local scope:

def my_function():
    x = 10    # x only exists inside this function
    print(x)

my_function()   # 10
print(x)        # Error! x does not exist outside the function

Why is that a good thing? Every function gets its own private workspace. Two functions can both use a variable called total without ever interfering. A variable made outside every function is global, and functions can read it:

tax_rate = 0.2          # global

def add_tax(price):
    return price + price * tax_rate

print(add_tax(100))     # 120.0

A function can read a global variable, but assigning to that name inside the function creates a new local variable instead of changing the global one. Rather than reaching outside, pass values in as parameters and send results out with return. That keeps functions simple and easy to test.

Putting functions to work

def calculate_total(price, quantity, tax_rate=0.1):
    subtotal = price * quantity
    tax = subtotal * tax_rate
    total = subtotal + tax
    return total

def print_receipt(item, price, quantity):
    total = calculate_total(price, quantity)
    print(f"Item:     {item}")
    print(f"Price:    ${price:.2f}")
    print(f"Quantity: {quantity}")
    print(f"Total:    ${total:.2f}")
    print("---")

print_receipt("Apple", 0.50, 6)
print_receipt("Bread", 2.99, 2)
print_receipt("Milk",  1.25, 3)

Notice how print_receipt calls calculate_total. Functions can use other functions, so you build big things from small reliable pieces. Each function does one job. This idea of breaking a big problem into smaller problems is called decomposition, and it is a core skill of every good programmer.

Rule of thumb: if you find yourself writing the same block of code more than once, turn it into a function. A function should do one thing and do it well. If a function is getting very long and doing many different things, split it into smaller functions.

Writing good functions

  • Pick a verb for the name. calculate_total, get_name and is_even tell you what happens.
  • Keep it small. If you cannot describe the job in one sentence, split it.
  • Add a docstring. A short note under the def line explains what it does.
  • Return a value instead of printing, unless showing something is the job.
  • Avoid secrets. A function should depend only on its parameters, not on hidden variables.
def is_even(number):
    """Return True if number is even, otherwise False."""
    return number % 2 == 0

print(is_even(4))   # True
print(is_even(7))   # False

Functions that return True or False are very handy inside an if: if is_even(n): reads almost like English. Test your functions with a few different inputs, including odd ones like 0 and negative numbers.

Functions that take any number of values

Sometimes you do not know how many arguments will come. A parameter that starts with a star collects all extra arguments into a tuple:

def total(*numbers):
    result = 0
    for n in numbers:
        result += n
    return result

print(total(1, 2))          # 3
print(total(5, 10, 15, 20)) # 50

This is how print() can accept any number of items. You do not need this every day, but it is good to recognize it when you see *args in other code.

Functions are also values. You can store one in a variable or put it in a dictionary, which is the trick used in the calculator project later:

def square(n):
    return n * n

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

Key takeaways

  • def name(parameters): defines a function, and name(arguments) calls it
  • Parameters are the inputs. Arguments are the actual values you pass
  • return sends a value back and ends the function. No return means None
  • Default values like exponent=2 make arguments optional
  • Variables made inside a function are local and disappear after it ends
  • Small, well named functions that do one job are the heart of clean code
Sign up to track your progress Mark lessons as read and pick up where you left off Sign up free to unlock this practice Your first practice lesson is free to try. Create an account to unlock the rest and save your progress