Skip to content

Tail Recursion

Tail recursion is an optimization where the recursive call is the last operation in a function. Some languages optimize tail calls, but Python doesn't support tail call optimization (TCO) by design.


Tail Recursive Pattern

In a tail recursive function, the recursive call is the final operation:

# Tail recursive: recursive call is the last statement
def factorial_tail(n, accumulator=1):
    if n <= 1:
        return accumulator
    # The return of the recursive call is the last operation
    return factorial_tail(n - 1, n * accumulator)

print(factorial_tail(5))   # 120
print(factorial_tail(5, 1))  # 120

Compare with non-tail recursion:

# Non-tail recursive: multiplication happens after recursive call
def factorial_non_tail(n):
    if n <= 1:
        return 1
    return n * factorial_non_tail(n - 1)  # Returns result of multiply, not recursion

Why Tail Recursion Matters

In languages with TCO (Scheme, Scala, some functional languages), tail recursive functions don't grow the call stack:

# Without TCO, this pattern uses O(n) stack space in any language
def count_down_tail(n):
    if n <= 0:
        print("Done!")
        return
    print(n)
    return count_down_tail(n - 1)  # Python: still uses O(n) stack

count_down_tail(5)
# Output:
# 5
# 4
# 3
# 2
# 1
# Done!

Converting to Iterative (Python Best Practice)

Since Python doesn't optimize tail calls, convert tail recursive code to iteration:

# Tail recursive version (uses stack)
def sum_tail_recursive(numbers, index=0, accumulator=0):
    if index >= len(numbers):
        return accumulator
    return sum_tail_recursive(numbers, index + 1, accumulator + numbers[index])

# Iterative version (better for Python)
def sum_iterative(numbers):
    accumulator = 0
    for num in numbers:
        accumulator += num
    return accumulator

numbers = [1, 2, 3, 4, 5]
print(sum_tail_recursive(numbers))  # 15
print(sum_iterative(numbers))        # 15

Key Takeaway for Python

Python deliberately doesn't support TCO. When you identify tail recursive code: 1. Convert to iteration for better performance 2. Or use accumulator pattern if recursion is clearer 3. Accept the O(n) stack space usage if recursion adds clarity