Skip to main content

What are Functions in Python?

Functions are reusable blocks of code that perform a specific task. They help you organise code, avoid repetition, and make programs easier to understand and maintain.

Why use functions?

Functions let you write code once and use it multiple times. Instead of repeating the same logic, you define it once and call it whenever needed.

Example 1
# Without functions - repetitive code
numbers1 = [1, 2, 3, 4, 5]
total1 = 0
for num in numbers1:
total1 += num
print(total1)
>>> 15

numbers2 = [10, 20, 30]
total2 = 0
for num in numbers2:
total2 += num
print(total2)
>>> 60

With functions, you define the logic once and reuse it.

Example 2
# With functions - reusable code
def calculate_sum(numbers):
total = 0
for num in numbers:
total += num
return total

print(calculate_sum([1, 2, 3, 4, 5]))
>>> 15

print(calculate_sum([10, 20, 30]))
>>> 60

Functions also make code more readable by giving operations clear names.

Example 3
# Clear intent with function names
def is_even(number):
return number % 2 == 0

def get_discount_price(price, discount_percent):
return price * (1 - discount_percent / 100)

print(is_even(8))
>>> True

print(get_discount_price(100, 20))
>>> 80.0

How functions work

A function takes input (parameters), performs operations, and optionally returns output. Think of it as a machine: you feed it inputs, it processes them, and gives you a result.

Example 4
def greet(name):
message = f"Hello, {name}!"
return message

result = greet("Alice")
print(result)
>>> Hello, Alice!

Functions can work without parameters or return values.

Example 5
def say_hello():
print("Hello, World!")

say_hello()
>>> Hello, World!

# This function doesn't return anything (returns None)
result = say_hello()
print(result)
>>> Hello, World!
>>> None

Function components

A function definition has several parts: the def keyword, function name, parameters, and body.

Example 6
def multiply(a, b):  # Function definition
"""Multiply two numbers and return the result."""
result = a * b # Function body
return result # Return statement

product = multiply(5, 3) # Function call
print(product)
>>> 15

The function name should describe what it does. Parameters are placeholders for values passed when calling the function.

Example 7
def calculate_area(length, width):
"""Calculate the area of a rectangle."""
return length * width

area = calculate_area(5, 3)
print(area)
>>> 15

Functions can have default parameter values, making some arguments optional.

Example 8
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"

print(greet("Alice"))
>>> Hello, Alice!

print(greet("Bob", "Hi"))
>>> Hi, Bob!

Types of functions

Python has several types of functions, each suited to different tasks.

Built-in functions

Python provides many built-in functions that are always available, like len(), print(), max(), and sorted().

Example 9
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
print(len(numbers))
>>> 8

print(max(numbers))
>>> 9

print(sorted(numbers))
>>> [1, 1, 2, 3, 4, 5, 6, 9]

See Python Built-in Functions for a comprehensive guide.

User-defined functions

You create user-defined functions with the def keyword. They're the most common way to organise your code.

Example 10
def calculate_total(price, tax_rate=0.20):
return price * (1 + tax_rate)

print(calculate_total(100))
>>> 120.0

See User-Defined Functions in Python for details on creating custom functions.

Anonymous functions

Anonymous functions, created with lambda, don't have names. They're useful for short operations.

Example 11
square = lambda x: x ** 2
print(square(5))
>>> 25

numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared)
>>> [1, 4, 9, 16, 25]

See Anonymous Functions in Python for more on lambda functions.

Recursive functions

Recursive functions call themselves to solve problems by breaking them into smaller subproblems.

Example 12
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)

print(factorial(5))
>>> 120

See Recursive Functions in Python for more on recursion.

Generator functions

Generator functions use yield to produce values lazily, making them memory-efficient for large sequences.

Example 13
def count_up_to(n):
count = 1
while count <= n:
yield count
count += 1

for num in count_up_to(5):
print(num)
>>> 1
>>> 2
>>> 3
>>> 4
>>> 5

See Generator Functions in Python for more on generators.

Higher-order functions

Higher-order functions take other functions as arguments or return functions.

Example 14
def apply_operation(x, y, operation):
return operation(x, y)

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

print(apply_operation(5, 3, add))
>>> 8

See Higher-Order Functions in Python for more on this pattern.

For a complete overview of all function types, see What are the Types of Functions in Python?.

Calling functions

To use a function, you call it by name and provide arguments (if required).

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

# Call with positional arguments
result = add(3, 5)
print(result)
>>> 8

# Call with keyword arguments
result = add(a=3, b=5)
print(result)
>>> 8

You can mix positional and keyword arguments, but positional arguments must come first.

Example 16
def create_profile(name, age, city):
return f"{name}, {age}, from {city}"

print(create_profile("Alice", age=25, city="London"))
>>> Alice, 25, from London

Functions can accept variable numbers of arguments using *args and **kwargs.

Example 17
def sum_all(*args):
return sum(args)

print(sum_all(1, 2, 3, 4, 5))
>>> 15

def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")

print_info(name="Alice", age=25)
>>> name: Alice
>>> age: 25

See also