How to Create a Function in Python

What you’ll build or solve

You’ll create your own Python functions using def, pass arguments into them, and return values back to the caller.

When this approach works best

This approach works best when you:

  • Keep repeating the same steps in different places and want one reusable function.
  • Want to turn a chunk of logic into a clear, named action like format_name() or calculate_total().
  • Need to test a small piece of code in isolation, then reuse it across a project.

Avoid this approach when:

  • You are writing a quick one-off script and the function would only be called once. Keeping it inline can be simpler.

Prerequisites

  • Python installed

Step-by-step instructions

1) Write a function with def

A function definition starts with def, followed by a name, parentheses, and a colon. The function body is indented.

def say_hello():
    print("Hello!")

Call it by adding parentheses:

say_hello()

What to look for: if your body is not indented, you will get an IndentationError.


2) Add parameters to accept input

Parameters let your function receive values from the call site.

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

Call it with arguments:

greet("Mina")
greet("Sam")

What to look for: if you call greet() without an argument, Python raises a TypeError because name is required.


3) Return a value with return

Use return when you want your function to produce a value you can store or pass into other code.

def double(number):
    return number * 2

result = double(6)
print(result)

If you do not return anything, the function returns None:

def log_message(text):
    print(f"[LOG] {text}")

value = log_message("Started")
print(value)  # None

What to look for: if you see None where you expected a value, add a return.


4) Use default values for optional parameters

Defaults let you call a function with fewer arguments when a value is optional.

def greet(name, punctuation="!"):
    return f"Hi, {name}{punctuation}"

print(greet("Mina"))
print(greet("Mina", punctuation=" :)"))

A common pattern is to put required parameters first and optional ones last.


5) Keep your function small and predictable

A function is easier to reuse when it does one job and has a clear input and output.

Small example:

def clean_username(raw):
    return raw.strip().lower()

print(clean_username("  Ada "))

Readable multi-step example:

def make_display_name(first, last):
    first_clean = first.strip().title()
    last_clean = last.strip().title()
    return f"{first_clean} {last_clean}"

Examples you can copy

Example 1: Return a formatted string

def format_name(first, last):
    first = first.strip().title()
    last = last.strip().title()
    return f"{last}, {first}"

print(format_name("ada", "lovelace"))

Example 2: Use a default parameter

def build_greeting(name, language="en"):
    if language == "en":
        return f"Hello, {name}!"
    elif language == "es":
        return f"Hola, {name}!"
    return f"Hi, {name}!"

print(build_greeting("Mina"))
print(build_greeting("Mina", language="es"))

Example 3: Validate input and return a boolean

def is_adult(age):
    return age >= 18

print(is_adult(17))
print(is_adult(25))

Example 4: Organize a script with a main block

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

def main():
    total = add(2, 3)
    print(total)

if __name__ == "__main__":
    main()

Use this pattern when you want your file to be both runnable and importable.


Common mistakes and how to fix them

Mistake 1: Forgetting to indent the function body

You might write:

def say_hi():
print("Hi")

Why it breaks: Python uses indentation to mark code blocks.

Correct approach:

def say_hi():
    print("Hi")

Mistake 2: Expecting a return value from a function that only prints

You might write:

def total_price(price, tax):
    print(price + tax)

total = total_price(10, 2)
print(total)

Why it breaks: the function prints a value but returns None.

Correct approach:

def total_price(price, tax):
    return price + tax

total = total_price(10, 2)
print(total)

Troubleshooting

  • If you see IndentationError, indent the function body with consistent spaces, usually 4.
  • If you see TypeError: missing required positional argument, pass all required arguments or add a default value.
  • If you see NameError when calling your function, define the function earlier in the file or import it correctly.
  • If you see None but expected a value, add return and return the computed result.
  • If you see TypeError: 'int' object is not callable, you overwrote your function name with a variable. Rename one of them.

Quick recap

  • Define a function with def name(): and indent the body.
  • Add parameters in the parentheses to accept input.
  • Use return to send a value back to the caller.
  • Use default values for optional parameters.
  • Keep functions small with clear inputs and outputs.