Defining and calling a function

A function is a named, reusable block of code. Define it with def, call it with parentheses:

def greet(name):
    """Return a greeting for name."""      # docstring
    return f"Hello, {name}!"

message = greet("Ada")
print(message)
print(greet("Linus"))
print(greet.__doc__)
Hello, Ada! Hello, Linus! Return a greeting for name.

The value after return is sent back to the caller. A function with no return (or a bare return) gives back None. Functions must be defined before they are called.

Parameters, defaults and keyword arguments

def power(base, exponent=2):
    return base ** exponent

print(power(3))            # uses default exponent
print(power(3, 3))
print(power(exponent=4, base=2))   # keyword args, any order

def describe(name, *, age):     # everything after * must be keyword
    return f"{name} is {age}"
print(describe("Ada", age=36))
9 27 16 Ada is 36

Parameters with defaults must come after those without. Never use a mutable default such as items=[] — the same list is shared across every call. Use items=None and create the list inside.

Returning multiple values

def min_max(values):
    return min(values), max(values)   # returns a tuple

low, high = min_max([4, 9, 1, 7])
print(low, high)

def divide(a, b):
    if b == 0:
        return None            # early return on bad input
    return a / b
print(divide(10, 4), divide(1, 0))
1 9 2.5 None

*args and **kwargs

Accept any number of positional arguments with *args (a tuple) and any keyword arguments with **kwargs (a dict):

def total(*numbers):
    return sum(numbers)
print(total(1, 2, 3), total())

def tag(name, **attrs):
    parts = " ".join(f'{k}="{v}"' for k, v in attrs.items())
    return f"<{name} {parts}>"
print(tag("a", href="/", target="_blank"))

# unpacking the other way
nums = [3, 5, 7]
print(total(*nums))
opts = {"href": "/x"}
print(tag("a", **opts))
6 0 <a href="/" target="_blank"> 15 <a href="/x">

Scope: local vs global

counter = 0          # global

def bump():
    local = 1        # exists only inside bump
    global counter
    counter += local

bump(); bump()
print(counter)

def outer():
    x = "outer"
    def inner():
        nonlocal x
        x = "changed by inner"
    inner()
    return x
print(outer())
2 changed by inner

A function can read global variables freely, but to assign one you must declare global. In practice, prefer passing values in and returning results — functions that rely on globals are hard to test.

Lambda functions

A lambda is a one-expression anonymous function, mostly used as a key or callback:

square = lambda n: n * n
print(square(6))

people = [("Ada", 36), ("Linus", 54), ("Grace", 85)]
print(sorted(people, key=lambda p: p[1]))
print(list(map(lambda p: p[0].upper(), people)))
print(list(filter(lambda p: p[1] > 40, people)))
36 [('Ada', 36), ('Linus', 54), ('Grace', 85)] ['ADA', 'LINUS', 'GRACE'] [('Linus', 54), ('Grace', 85)]

If a lambda needs a name, or more than one expression, write a normal def instead.

Write and test your own functions in the app — the Coding Python app runs real Python 3 on your phone, with examples, quizzes and challenges built in.
Get it free

Recursion

A function may call itself. Every recursive function needs a base case that stops the recursion:

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

def fib(n):
    return n if n < 2 else fib(n - 1) + fib(n - 2)

print(factorial(5), fib(10))
print([fib(i) for i in range(10)])
120 55 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Python's default recursion limit is 1,000 levels. Deep recursion is usually better rewritten as a loop. The naive fib above is exponentially slow; the standard library lesson shows how functools.lru_cache fixes it in one line.

Type hints and docstrings

def area(width: float, height: float) -> float:
    """Return the area of a rectangle.

    Args:
        width: horizontal size in metres.
        height: vertical size in metres.
    """
    return width * height

print(area(2.5, 4))
help(area)
10.0 Help on function area in module __main__: area(width: float, height: float) -> float Return the area of a rectangle. ...

Hints are ignored at runtime but make code self-documenting and let editors catch mistakes. Next lesson: modelling things with classes and objects.

Frequently asked questions

What is the difference between a parameter and an argument?

A parameter is the name in the function definition (def f(x)); an argument is the value you pass when calling (f(5)). People use the words interchangeably in conversation.

What does return do in Python?

return ends the function and sends a value back to the caller. Code after return never runs. A function without return gives None.

What are *args and **kwargs?

*args collects extra positional arguments into a tuple; **kwargs collects extra keyword arguments into a dictionary. The names args and kwargs are convention, only the stars matter.

When should I use a lambda?

For short throwaway functions passed to sorted(), map(), filter() or GUI callbacks. If it needs a name or more than one expression, use def.