W3docs

Python Functions

Learn how to define and call Python functions, use parameters, default arguments, *args, **kwargs, return values, scope, and docstrings.

A function is a named, reusable block of code that performs a specific task. Functions let you write logic once and call it from anywhere in your program — making your code shorter, easier to read, and simpler to test. This chapter covers everything you need to work confidently with Python functions: definition, parameters, return values, default arguments, *args and **kwargs, scope, docstrings, type hints, recursion, and first-class function usage.

Defining a Function

Use the def keyword, a name, parentheses, and a colon. The body is indented one level.

def greet(name):
    print("Hello, " + name)

The function is not executed until you call it. Nothing happens at definition time except that Python stores the function object under the given name.

Calling a Function

Pass arguments inside the parentheses matching the parameter names in the definition.

python— editable, runs on the server

Return Values

A function can send a result back to the caller with the return statement. Without return, Python returns None.

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

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

Once return executes, the function stops immediately — any code after it in the same function body is unreachable.

Returning Multiple Values

Python lets you return several values as a tuple, which you can unpack on the calling side.

import math

def circle_stats(radius):
    area = math.pi * radius ** 2
    circumference = 2 * math.pi * radius
    return area, circumference

area, circ = circle_stats(5)
print(round(area, 2))   # 78.54
print(round(circ, 2))   # 31.42

Parameters and Arguments

TermMeaning
ParameterVariable name in the function definition
ArgumentActual value passed when calling the function

Python supports several ways to pass arguments.

Positional Arguments

Arguments are matched to parameters in order.

def describe(name, age):
    print(name, "is", age, "years old")

describe("Bob", 25)   # Bob is 25 years old

Keyword Arguments

You can pass arguments by name, in any order.

describe(age=25, name="Bob")   # Bob is 25 years old

Default Parameter Values

Provide a fallback value that is used when the caller omits that argument.

def greet(name="World"):
    print("Hello, " + name)

greet()         # Hello, World
greet("Alice")  # Hello, Alice

Gotcha: never use a mutable object (list, dict) as a default value — it is created once at definition time and shared across all calls. Use None as the default and create the object inside the body instead.

# Correct pattern for a mutable default
def append_item(item, lst=None):
    if lst is None:
        lst = []
    lst.append(item)
    return lst

Arbitrary Positional Arguments (*args)

Prefix a parameter name with * to collect any number of positional arguments into a tuple.

def total(*numbers):
    return sum(numbers)

print(total(1, 2, 3))    # 6
print(total(10, 20))     # 30

Arbitrary Keyword Arguments (**kwargs)

Prefix with ** to collect any number of keyword arguments into a dictionary.

def describe_person(**info):
    for key, value in info.items():
        print(key + ": " + str(value))

describe_person(name="Alice", age=30, city="Paris")
# name: Alice
# age: 30
# city: Paris

Combining Parameter Types

When you mix parameter types, the order must be: positional, *args, keyword-only, **kwargs.

def log(level, *messages, separator=" | ", **meta):
    print(level.upper(), separator.join(messages), meta)

log("info", "started", "ready", separator=" — ", version="1.0")
# INFO started — ready {'version': '1.0'}

Variable Scope

Python's scoping rules follow the LEGB rule: Local → Enclosing → Global → Built-in.

A variable defined inside a function is local — it cannot be accessed outside.

def my_func():
    x = 10          # local to my_func
    print(x)

my_func()
# print(x)  # NameError: name 'x' is not defined

To read or modify a global variable inside a function, declare it with global.

x = 10

def change_x():
    global x
    x = 20

change_x()
print(x)   # 20

Use global sparingly — functions that depend on global state are harder to test and reuse. See Python Variables and Global Variables for a deeper look at scope.

Docstrings

A docstring is a string literal placed immediately after the def line. It documents what the function does, what it accepts, and what it returns. Python stores it in the function's __doc__ attribute and tools like help() display it.

def add(a, b):
    """Return the sum of a and b.

    Args:
        a: First number.
        b: Second number.

    Returns:
        The sum as a number.
    """
    return a + b

print(add.__doc__)
# Return the sum of a and b.
# ...

Type Hints

Type hints (PEP 484) let you annotate parameter and return types. Python does not enforce them at runtime, but editors, linters, and mypy use them to catch bugs early.

def multiply(a: float, b: float) -> float:
    return a * b

print(multiply(3, 4))      # 12
print(multiply(2.5, 2.0))  # 5.0

Recursion

A function can call itself. This is called recursion and is useful for problems with a naturally recursive structure (trees, factorials, etc.). Every recursive function needs a base case that stops the recursion.

def factorial(n):
    if n == 0 or n == 1:   # base case
        return 1
    return n * factorial(n - 1)

print(factorial(5))   # 120
print(factorial(0))   # 1

Python limits recursion depth (default 1000) to prevent stack overflows. For deep recursion, prefer an iterative approach or use sys.setrecursionlimit.

Functions as First-Class Objects

In Python, functions are objects. You can store them in variables, pass them as arguments, and return them from other functions.

def apply(func, value):
    return func(value)

def double(n):
    return n * 2

print(apply(double, 7))   # 14

This is the foundation for lambda functions, higher-order functions, and decorators.

Built-in Functions vs. User-Defined Functions

Python ships with many built-in functionsprint(), len(), range(), sum(), sorted() — that are always available without an import. User-defined functions are the ones you write with def. Both follow identical call syntax.

Best Practices

  • Name functions as verbs: calculate_tax() is clearer than tax().
  • Do one thing: a function that validates, saves, and sends an email is three functions waiting to be born.
  • Write a docstring: even a single sentence describing the purpose is valuable.
  • Avoid side effects where possible: functions that return values and change no global state are easier to test.
  • Keep signatures short: more than three or four parameters is a signal to group related data into a class or dict.
  • Use type hints: they serve as lightweight documentation and enable static analysis.

Practice

Practice
Which keyword is used to define a function in Python?
Which keyword is used to define a function in Python?
Was this page helpful?