User-Defined Functions in Python
User-defined functions are created with the def keyword. They let you encapsulate code into reusable blocks.
Contents
Basic function definition
Use def followed by the function name and parentheses to define a function.
def greet():
print("Hello, World!")
greet()
>>> Hello, World!
Functions can take parameters to accept input values.
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
>>> Hello, Alice!
Function parameters
Functions can accept multiple parameters, including positional and keyword arguments.
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.
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.
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.
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.
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.
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.
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.
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.
def add(a: int, b: int) -> int:
return a + b
print(add(3, 5))
>>> 8
Annotations don't enforce types but provide useful documentation.
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.
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.
count = 0
def increment():
global count
count += 1
increment()
increment()
print(count)
>>> 2
Functions can access variables from enclosing scopes, creating closures.
def outer_function(x):
def inner_function(y):
return x + y
return inner_function
add_five = outer_function(5)
print(add_five(3))
>>> 8