Codectionary / Developer documentation / Python

def

The def keyword in Python is used to define functions - reusable blocks of code that perform specific tasks. Functions are fundamental to organizing code, avoiding repetition, and making programs more maintainable. A function can accept inputs (parameters), perform operations, and return outputs. Functions are one of the core building blocks of clean, modular Python code.

Syntax

def function_name(parameters):
    # function body
    return value

Examples

A small working example

Follow the values through this example, then change one input.

def total(price, quantity):
    return price * quantity

print(total(12, 3))

Basic Functions

Simple function definitions with and without parameters.

# Function with no parameters
def greet():
    print("Hello, World!")

greet()  # Call the function

# Function with parameters
def greet_person(name):
    print(f"Hello, {name}!")

greet_person("Alice")  # Hello, Alice!
greet_person("Bob")    # Hello, Bob!

Return Values

Functions that return values for use in other parts of the program.

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

sum_result = add(5, 3)
print(sum_result)  # 8

# Function with multiple return values
def calculate(x, y):
    addition = x + y
    subtraction = x - y
    multiplication = x * y
    return addition, subtraction, multiplication

a, s, m = calculate(10, 5)
print(f"Add: {a}, Subtract: {s}, Multiply: {m}")

Default Parameters

Setting default values for parameters that can be overridden.

def create_profile(name, age=18, country="USA"):
    print(f"Name: {name}")
    print(f"Age: {age}")
    print(f"Country: {country}")
    print()

# Using all defaults
create_profile("Alice")

# Overriding some defaults
create_profile("Bob", 25)

# Overriding all
create_profile("Charlie", 30, "UK")

# Using keyword arguments
create_profile("David", country="Canada")

Variable Arguments

Using *args and **kwargs to accept flexible number of arguments.

# *args - variable positional arguments
def sum_all(*numbers):
    total = 0
    for num in numbers:
        total += num
    return total

print(sum_all(1, 2, 3))        # 6
print(sum_all(10, 20, 30, 40)) # 100

# **kwargs - variable keyword arguments
def print_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_info(name="Alice", age=25, city="New York")

# Combining both
def display_data(title, *args, **kwargs):
    print(f"=== {title} ===")
    print("Positions:", args)
    print("Keywords:", kwargs)

display_data("User Info", "Item1", "Item2", name="Bob", role="Admin")

Docstrings and Type Hints

Documenting functions and specifying expected types.

def calculate_bmi(weight: float, height: float) -> float:
    """
    Calculate Body Mass Index.
    
    Args:
        weight (float): Weight in kilograms
        height (float): Height in meters
    
    Returns:
        float: BMI value rounded to 2 decimal places
    """
    bmi = weight / (height ** 2)
    return round(bmi, 2)

result = calculate_bmi(70, 1.75)
print(f"BMI: {result}")

# Access docstring
print(calculate_bmi.__doc__)

Nested Functions

Defining functions inside other functions for encapsulation.

def outer_function(x):
    print(f"Outer function received: {x}")
    
    def inner_function(y):
        return y * 2
    
    result = inner_function(x)
    print(f"Inner function returned: {result}")
    return result

final = outer_function(5)
print(f"Final result: {final}")

# Practical example - validation
def process_user(name, age):
    def validate_name(n):
        return len(n) > 0 and n.isalpha()
    
    def validate_age(a):
        return 0 < a < 150
    
    if not validate_name(name):
        return "Invalid name"
    if not validate_age(age):
        return "Invalid age"
    
    return f"User {name} ({age}) registered successfully"

print(process_user("Alice", 25))

Best practices

  • Use clear, descriptive function names that indicate what the function does (calculate_total, not calc)
  • Keep functions focused on a single task (Single Responsibility Principle)
  • Add docstrings to explain what the function does, its parameters, and return value
  • Use type hints to make your function signatures clearer and enable better IDE support
  • Limit function length - if it's too long, consider breaking it into smaller functions
  • Use default parameter values wisely - they should represent the most common use case

At a glance

Purpose
Scripting and general-purpose applications
File extension
.py
Runs in
Python interpreter
Usually used with
Python standard library and packages

In plain English

def gives a reusable operation a name. Indentation groups the statements that belong to it.

What you’ll learn

  • Define a function.
  • Pass inputs.
  • Return a result.

Before you start: if

Breaking down the syntax

def
Starts a function definition.
:
Begins the indented body.
return
Ends the call and supplies a value.

How it works

Define

Create the function object.

Call

Bind arguments to parameters.

Return

Send a result to the caller.

When should I use this?

Group a focused operation that needs a clear name or reuse.

Common mistakes

A common trap

The function body must be indented.

Incorrect

def double(n):
return n * 2

Corrected

def double(n):
    return n * 2

Compare approaches

  • def: Named functions with statements.
  • lambda: A small function expressed by one expression.

Explore deeper

Default values are evaluated once

A mutable default such as [] is shared by calls that omit that argument. Use None as a sentinel and create a fresh list inside when each call needs its own list.

Specifications & further reading

Related Python documentation

lambda
A lambda is a small, anonymous, single-expression function, created without the def keyword or a name. Lambdas are restricted to a single expression whose result is automatically returned - they can't contain multiple statements or assignments. They're most useful as short, throwaway functions passed as arguments to other functions like sorted(), map(), and filter().
return
The return statement exits a function immediately and optionally sends a value back to the caller. A function can return any type - including multiple values as a tuple - or nothing at all, in which case it implicitly returns None. Once return executes, no further code in the function runs, making it useful for early exits as well as producing a final result.
*args and **kwargs
*args and **kwargs let a function accept a variable number of arguments. *args collects any extra positional arguments into a tuple, while **kwargs collects extra keyword arguments into a dictionary. The names 'args' and 'kwargs' are just convention - what matters is the * and ** prefixes. This pattern is common in wrapper functions, decorators, and APIs that need to stay flexible about their inputs.
Decorators
A decorator is a function that wraps another function to extend or modify its behavior, without changing its actual source code. Decorators use the @decorator_name syntax placed directly above a function definition, which is shorthand for passing the function into the decorator and reassigning the result. They're widely used for logging, timing, access control, caching, and validation.