DocsHub
PythonIntermediate

Factorial

Learn how to calculate the factorial of a number in Python using loops, recursion, and more.

Factorial

Problem

The factorial of a number n is the product of all positive integers from 1 to n. It is written as n!.

0! = 1          (by definition)
1! = 1
2! = 2 × 1 = 2
3! = 3 × 2 × 1 = 6
4! = 4 × 3 × 2 × 1 = 24
5! = 5 × 4 × 3 × 2 × 1 = 120
Input:  5
Output: 120

Input:  0
Output: 1

Input:  10
Output: 3628800

Logic

  1. If n is 0 or 1 — return 1 (base case)
  2. Otherwise multiply n × (n-1) × (n-2) × ... × 1
  3. Keep multiplying until you reach 1

Flow

Yes No Yes No Start n == 0 or n == 1? Return 1 result = 1i = n i >= 1? result = result x i i -= 1 Return result

Solution 1 — using a loop

Multiply from n down to 1, accumulating the result.

def factorial(n):
    # factorial is not defined for negative numbers
    if n < 0:
        raise ValueError("Factorial is not defined for negative numbers.")

    # base case — 0! = 1 by definition
    if n == 0:
        return 1

    result = 1

    # multiply result by every number from n down to 1
    for i in range(n, 0, -1):
        result *= i   # result = result × i

    return result


print(factorial(0))    # 1
print(factorial(1))    # 1
print(factorial(5))    # 120
print(factorial(10))   # 3628800

Code Execution — Solution 1

Trace through factorial(5):

range(5, 0, -1) gives 5, 4, 3, 2, 1

Stepiresult = result × iresult
Start1
1st51 × 55
2nd45 × 420
3rd320 × 360
4th260 × 2120
5th1120 × 1120
Done120

Trace through factorial(0):

n == 0 → immediately returns 1 without entering the loop.


Solution 2 — multiplying from 1 upward

Same idea — just loop from 1 to n instead of n down to 1. Same result either way.

def factorial(n):
    if n < 0:
        raise ValueError("Factorial is not defined for negative numbers.")
    if n == 0:
        return 1

    result = 1

    # multiply from 1 up to n
    for i in range(1, n + 1):
        result *= i

    return result


print(factorial(5))    # 120
print(factorial(6))    # 720
print(factorial(10))   # 3628800

Code Execution — Solution 2

Trace through factorial(5):

range(1, 6) gives 1, 2, 3, 4, 5

Stepiresult = result × iresult
Start1
1st11 × 11
2nd21 × 22
3rd32 × 36
4th46 × 424
5th524 × 5120
Done120

Both Solution 1 and 2 give the same result — multiplication is commutative, so order does not matter.


Solution 3 — using recursion

Factorial is defined recursively — n! = n × (n-1)!. This maps perfectly to a recursive function.

def factorial(n):
    if n < 0:
        raise ValueError("Factorial is not defined for negative numbers.")

    # base case — stop here
    if n == 0 or n == 1:
        return 1

    # recursive case — n × factorial of (n-1)
    return n * factorial(n - 1)


print(factorial(0))    # 1
print(factorial(1))    # 1
print(factorial(5))    # 120
print(factorial(10))   # 3628800

Code Execution — Solution 3

Trace through factorial(5):

factorial(5)
  = 5 × factorial(4)
        = 4 × factorial(3)
              = 3 × factorial(2)
                    = 2 × factorial(1)
                          = 1   ← base case
                    = 2 × 1 = 2
              = 3 × 2 = 6
        = 4 × 6 = 24
  = 5 × 24 = 120

The call stack builds up to factorial(1), then unwinds — each level multiplies its n by the result returned from below.

Every recursive function needs two things:

  • Base case — the condition that stops the recursion. Here it is n == 0 or n == 1.
  • Recursive case — the function calling itself with a smaller input. Here it is n * factorial(n - 1).

Without the base case, the function would call itself forever — RecursionError.


Solution 4 — using math.factorial

Python's standard library has a built-in factorial function. Fastest and most reliable.

import math

print(math.factorial(0))    # 1
print(math.factorial(5))    # 120
print(math.factorial(10))   # 3628800
print(math.factorial(20))   # 2432902008176640000

Solution 5 — using reduce()

Multiply all numbers from 1 to n together using reduce().

from functools import reduce

def factorial(n):
    if n < 0:
        raise ValueError("Factorial is not defined for negative numbers.")
    if n == 0:
        return 1

    # reduce multiplies pairs left to right
    # range(1, n+1) = 1, 2, 3, ..., n
    return reduce(lambda a, b: a * b, range(1, n + 1))


print(factorial(5))    # 120
print(factorial(10))   # 3628800

Code Execution — Solution 5

Trace through factorial(5):

range(1, 6) = [1, 2, 3, 4, 5]

reduce(lambda a, b: a * b, [1, 2, 3, 4, 5]):

Stepaba * b
1st122
2nd236
3rd6424
4th245120

Result: 120


Bonus — factorial of large numbers

Python handles arbitrarily large integers natively — no overflow:

import math

print(math.factorial(50))
# 30414093201713378043612608166979581188299763898377856000000000000

print(math.factorial(100))
# 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000

This is one of Python's great strengths — you never have to worry about integer overflow.


Recursive vs iterative — when to use which

ApproachProsCons
LoopFast, no call stack limitSlightly more code
RecursionElegant, mirrors the definitionSlower, limited by recursion depth
math.factorialFastest, built-inNo learning value
reduceFunctional styleLess readable for beginners

Python's default recursion limit is 1000 calls deep. factorial(1000) would cause a RecursionError with the recursive solution. Use the loop or math.factorial for large inputs.


Which solution to use?

SolutionHowBest when
Solution 1Loop downwardEasy to understand
Solution 2Loop upwardSame thing, different direction
Solution 3RecursionLearning recursion
Solution 4math.factorialReal projects
Solution 5reduce()Learning functional style

Output

1
1
120
3628800

On this page