Last updated: 2026-05-21

Python Functions

Functions are reusable blocks of code that perform a specific task. They are one of the most important tools in any programming language — they reduce repetition, organise logic, and make code easier to read, test, and maintain. Python's approach to functions is clean and expressive, with several features that go beyond what you may be used to from JavaScript.


Defining and Calling a Function

Functions are defined with the def keyword, followed by the function name, parameters in parentheses, and a colon. The function body is indented:

def greet(name):
    return f"Hello, {name}!"

print(greet("Wariz"))   # Hello, Wariz!

A function that does not explicitly return a value returns None automatically.


Parameters and Arguments

Parameters are the placeholders defined in the function signature. Arguments are the actual values passed when calling the function.

def add(a, b):        # a and b are parameters
    return a + b

result = add(5, 3)    # 5 and 3 are arguments
print(result)         # 8

Default parameters

Parameters can have default values. If the caller does not provide an argument for that parameter, the default is used:

def greet(name, greeting="Hello"):
    return f"{greeting}, {name}!"

print(greet("Wariz"))              # Hello, Wariz!
print(greet("Wariz", "Welcome"))   # Welcome, Wariz!

Parameters with defaults must come after parameters without defaults:

def greet(greeting="Hello", name):   # ❌ SyntaxError
    pass

def greet(name, greeting="Hello"):   # ✅ Correct
    pass

Keyword arguments

When calling a function, you can pass arguments by name — in any order:

def describe(name, age, city):
    return f"{name}, {age}, from {city}"

print(describe(age=20, city="Lagos", name="Wariz"))
# Wariz, 20, from Lagos

Mixing positional and keyword arguments is allowed, but positional arguments must come first:

print(describe("Wariz", city="Lagos", age=20))   # ✅
print(describe(name="Wariz", 20, "Lagos"))        # ❌ SyntaxError

*args — Variable Positional Arguments

When a function needs to accept any number of positional arguments, use *args. It collects all extra positional arguments into a tuple:

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

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

The name args is a convention — the * is what matters. You could write *numbers, *values, etc.


**kwargs — Variable Keyword Arguments

**kwargs collects any number of keyword arguments into a dictionary:

def display_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

display_info(name="Wariz", age=20, city="Lagos")
# name: Wariz
# age: 20
# city: Lagos

Combining all parameter types

The order when combining all parameter types is: positional → *args → keyword-only → **kwargs:

def example(pos1, pos2, *args, keyword_only, **kwargs):
    print(pos1, pos2, args, keyword_only, kwargs)

example(1, 2, 3, 4, keyword_only="hello", extra="world")
# 1 2 (3, 4) hello {'extra': 'world'}

Return Values

A function can return any value — including multiple values at once (as a tuple):

def min_max(numbers):
    return min(numbers), max(numbers)

low, high = min_max([3, 1, 7, 2, 9])
print(low, high)    # 1 9

Returning multiple values and unpacking them into separate variables is idiomatic Python. Under the hood, the function returns a single tuple — the unpacking happens at the call site.


Variable Scope

A variable defined inside a function is local to that function — it cannot be accessed outside it:

def my_function():
    local_var = "I am local"
    print(local_var)    # ✅

my_function()
print(local_var)        # ❌ NameError: name 'local_var' is not defined

A variable defined outside any function is global — accessible anywhere in the module:

global_var = "I am global"

def my_function():
    print(global_var)   # ✅ Can read it

my_function()

The global keyword

To modify a global variable from inside a function, declare it with global:

count = 0

def increment():
    global count
    count += 1

increment()
increment()
print(count)    # 2

Use global sparingly — functions that modify global state are harder to test and reason about.


Lambda Functions

A lambda is a small, anonymous function defined in a single expression. It is Python's equivalent of JavaScript's arrow functions:

# Regular function
def double(n):
    return n * 2

# Lambda equivalent
double = lambda n: n * 2

print(double(5))    # 10

Syntax: lambda parameters: expression

Lambdas are limited to a single expression — they cannot contain multiple statements or a return keyword (the expression is implicitly returned).

Lambdas are most useful when passing a short function as an argument to another function:

numbers = [3, 1, 4, 1, 5, 9, 2]
numbers.sort(key=lambda x: -x)    # Sort in descending order
print(numbers)    # [9, 5, 4, 3, 2, 1, 1]

For anything more complex than a single expression, use a regular named function.


Higher-Order Functions

A higher-order function is a function that takes another function as an argument or returns one. Python has three built-in higher-order functions that are used constantly:

map()

Applies a function to every item in an iterable and returns a map object (convert to list if needed):

numbers = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, numbers))
print(doubled)    # [2, 4, 6, 8, 10]

filter()

Filters an iterable, keeping only items for which the function returns True:

numbers = [1, 2, 3, 4, 5, 6]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)    # [2, 4, 6]

sorted() with a key

Returns a new sorted list. The key argument accepts a function that computes the sort value:

users = [
    {"name": "Wariz", "age": 20},
    {"name": "Ada", "age": 25},
    {"name": "Aliyu", "age": 18}
]

by_age = sorted(users, key=lambda u: u["age"])
print(by_age[0]["name"])    # Aliyu — youngest first

Docstrings

A docstring is a string literal placed as the first statement in a function body. It documents what the function does and is accessible via help():

def add(a, b):
    """
    Returns the sum of two numbers.

    Args:
        a: The first number.
        b: The second number.

    Returns:
        The sum of a and b.
    """
    return a + b

help(add)

Docstrings are the standard way to document Python functions and are used by IDEs, documentation generators, and tools like Sphinx. They are a first-class part of Python's culture — well-documented functions are expected in professional Python code.


Functions as First-Class Objects

In Python, functions are first-class objects — they can be assigned to variables, stored in data structures, and passed as arguments:

def square(n):
    return n ** 2

def cube(n):
    return n ** 3

operations = [square, cube]

for op in operations:
    print(op(3))    # 9, then 27

This property is what makes higher-order functions, decorators, and callbacks possible.


Summary

ConceptPython Syntax
Define a functiondef name(params):
Return a valuereturn value
Default parameterdef f(x, y=10):
Keyword argumentf(x=1, y=2)
Variable positional argsdef f(*args):
Variable keyword argsdef f(**kwargs):
Return multiple valuesreturn a, b — returns a tuple
Lambda functionlambda x: x * 2
Apply function to iterablemap(func, iterable)
Filter iterablefilter(func, iterable)
Sort with custom keysorted(iterable, key=func)
Document a functionTriple-quoted docstring as first line