Chapter 4

Functions

4.0 Intro · 4.1 Functions · 4.2 Function Design · 4.3 Recursion

← → or Space to navigate · F for fullscreen

4.1 Functions

Defining, calling, parameters, return values, type annotations

Defining & Calling Functions

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

print(greet("Alice"))   # Hello, Alice!
  • def keyword defines a function.
  • The body is indented.
  • return sends a value back to the caller.
  • Without return, a function returns None.

Parameters & Arguments

def power(base, exp=2):     # default value
    return base ** exp

print(power(3))      # 9   (exp=2)
print(power(3, 3))   # 27  (exp=3)
print(power(exp=3, base=2)) # 8 (keyword)
Term Meaning
Parameter Variable in the function definition
Argument Value passed when calling

*args and **kwargs

# *args — variable positional arguments (tuple)
def total(*args):
    return sum(args)

print(total(1, 2, 3, 4))   # 10

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

describe(name="Alice", age=25, city="Rolla")

Full parameter order

def f(pos, /, normal, *, kw_only,
      **kwargs):
    ...
Type Example
Positional f(1)
Default f(x=2)
*args Collects extras → tuple
**kwargs Collects key=val → dict

4.2 Function Design

Scope, composition, docstrings, lambda

Scope

  • Local scope: variables inside a function.
  • Global scope: variables at the module level.
  • A function can read globals but not write to them without global.
x = 10   # global

def show():
    print(x)   # reads global — OK

def double():
    global x
    x *= 2     # modifies global — needs 'global'

Prefer returning values over modifying globals. Functions that depend only on their arguments are easier to test.

Function composition

def celsius_to_fahrenheit(c):
    return c * 9/5 + 32

def format_temp(c):
    f = celsius_to_fahrenheit(c)
    return f"{c}°C = {f:.1f}°F"

print(format_temp(100))   # 100°C = 212.0°F

Docstrings & Lambda

Docstrings

def area(radius):
    """Return the area of a circle.

    Args:
        radius: The radius (non-negative float).
    Returns:
        Area as a float.
    """
    import math
    return math.pi * radius ** 2

Access with help(area) or area.__doc__.

Lambda — small anonymous function

# Named function
def square(x): return x ** 2

# Equivalent lambda
square = lambda x: x ** 2

# Common use: sort key
words = ["banana", "kiwi", "apple"]
words.sort(key=lambda w: len(w))
print(words)   # ['kiwi', 'apple', 'banana']

Use def when the logic needs a name or more than one expression.

4.3 Recursion

Recursive functions · base cases · tracing calls

Recursion

A function that calls itself. Every recursive function needs:

  1. A base case — stops the recursion.
  2. A recursive case — moves toward the base case.

Without a base case, recursion runs forever → RecursionError.

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

print(factorial(5))   # 120
# 5 * 4 * 3 * 2 * 1 * 1 = 120
def fibonacci(n):
    if n <= 1:          # base case
        return n
    return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10))  # 55

Chapter 4 — Quick Reference

Concept Key syntax / notes
Define function def name(params): return value
Default param def f(x=10):
*args Collect extra positional → tuple
**kwargs Collect extra keyword → dict
Docstring Triple-quoted string as first statement
Lambda lambda args: expression
Scope Local vars stay local; use return
Recursion Must have a base case

End of Chapter 4

Next: Chapter 5 — Exceptions & Testing

try · except · raise · pytest · unittest · doctest