Every function call gets pushed onto the call stack. When a function returns, it's popped off. Recursion stacks multiple calls.
Call: factorial(3)
Stack: [factorial(3)]
Call: factorial(2)
Stack: [factorial(3), factorial(2)]
Call: factorial(1)
Stack: [factorial(3), factorial(2), factorial(1)]
factorial(1) returns 1
Stack: [factorial(3), factorial(2)]
factorial(2) returns 2
Stack: [factorial(3)]
factorial(3) returns 6
Stack: []
The stack has limited space. Python defaults to calls deep. Exceed this and you get RecursionError. This is why every recursion needs a base case that stops the stacking.