Skip to main content

User-Defined Functions in Python

User-defined functions are created with the def keyword. They let you encapsulate code into reusable blocks.

Basic function definition

Use def followed by the function name and parentheses to define a function.

Example 1
def greet():
print("Hello, World!")

greet()
>>> Hello, World!

Functions can take parameters to accept input values.

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

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

Function parameters

Functions can accept multiple parameters, including positional and keyword arguments.

Example 3
def calculate_area(length, width):
return length * width

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

You can use keyword arguments to make function calls more readable.

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

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

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

Example 5
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, city="London")
>>> name: Alice
>>> age: 25
>>> city: London

Default arguments

Default arguments provide fallback values when parameters aren't supplied.

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

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

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

Default arguments are evaluated once when the function is defined, not each time it's called.

Example 7
def add_item(item, items=[]):
items.append(item)
return items

# This can lead to unexpected behaviour
print(add_item("apple"))
>>> ['apple']
print(add_item("banana"))
>>> ['apple', 'banana']

# Better approach: use None as default
def add_item_safe(item, items=None):
if items is None:
items = []
items.append(item)
return items

print(add_item_safe("apple"))
>>> ['apple']
print(add_item_safe("banana"))
>>> ['banana']

Return values

Functions can return values using the return statement. If no return is specified, the function returns None.

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

result = add(3, 5)
print(result)
>>> 8

Functions can return multiple values as a tuple, which Python automatically unpacks.

Example 9
def divide_with_remainder(a, b):
quotient = a // b
remainder = a % b
return quotient, remainder

q, r = divide_with_remainder(17, 5)
print(f"Quotient: {q}, Remainder: {r}")
>>> Quotient: 3, Remainder: 2

You can return early from a function.

Example 10
def check_positive(number):
if number <= 0:
return False
return True

print(check_positive(5))
>>> True
print(check_positive(-3))
>>> False

Function annotations

Type hints can be added to function parameters and return values for documentation and type checking.

Example 11
def add(a: int, b: int) -> int:
return a + b

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

Annotations don't enforce types but provide useful documentation.

Example 12
def process_data(data: list[str], threshold: float = 0.5) -> dict[str, int]:
return {"count": len(data), "threshold": threshold}

result = process_data(["a", "b", "c"], 0.7)
print(result)
>>> {'count': 3, 'threshold': 0.7}

Variable scope

Variables defined inside a function are local to that function. Global variables can be accessed but require the global keyword to modify.

Example 13
x = 10  # Global variable

def show_scope():
x = 20 # Local variable
print(f"Local x: {x}")

show_scope()
>>> Local x: 20
print(f"Global x: {x}")
>>> Global x: 10

To modify a global variable, use the global keyword.

Example 14
count = 0

def increment():
global count
count += 1

increment()
increment()
print(count)
>>> 2

Functions can access variables from enclosing scopes, creating closures.

Example 15
def outer_function(x):
def inner_function(y):
return x + y
return inner_function

add_five = outer_function(5)
print(add_five(3))
>>> 8

See also