A recursive function calls itself on a smaller input and stops at a base case. The call stack holds the unfinished frames.
Goal
Write factorial and a recursive sum, and print both.
Base case first
def factorial(n):
if n < 0:
raise ValueError("n must be >= 0")
if n <= 1:
return 1
return n * factorial(n - 1)
print(factorial(0))
print(factorial(5))factorial(5) waits for factorial(4), and so on, until 1.
Recursion vs a loop
def sum_r(xs):
if not xs:
return 0
return xs[0] + sum_r(xs[1:])
def sum_i(xs):
acc = 0
for x in xs:
acc += x
return acc
nums = [12, 7, 2]
print(sum_r(nums), sum_i(nums))Same answer. The loop uses constant extra space. The recursive version builds n frames — fine for a kiosk list, not for a million rows.
Countdown
def countdown(n):
if n <= 0:
print("open")
return
print(n)
countdown(n - 1)
countdown(3)Pitfall
Missing base case → RecursionError. The smaller call must actually get smaller (n - 1, xs[1:]), not the same n.