How to find the factors of a number in Python

Learn how to find the factors of a number in Python. This guide covers different methods, tips, real-world applications, and common errors.

How to find the factors of a number in Python
Published on: 
Wed
Mar 25, 2026
Updated on: 
Thu
Mar 26, 2026
The Replit Team

Factors of a number are integers that divide it without a remainder. Python helps you identify these factors efficiently, often with a simple loop and the modulo operator, %.

In this article, you'll explore several techniques to find factors. Each method includes practical tips, real-world applications, and debugging advice to help you select the right approach for your project.

Using a simple loop to find factors

def find_factors(n):
   factors = []
   for i in range(1, n + 1):
       if n % i == 0:
           factors.append(i)
   return factors

print(find_factors(12))--OUTPUT--[1, 2, 3, 4, 6, 12]

The find_factors function iterates through every integer from 1 to the input number n, ensuring no potential factor is missed. The core of this method is the conditional check if n % i == 0, which uses the modulo operator (%) to test for divisibility.

When the remainder of the division is zero, the number i is confirmed as a factor and appended to the list. This brute-force approach is highly reliable and easy to understand, though it becomes less efficient as you work with very large numbers.

Basic techniques

Beyond the straightforward loop, you can leverage Python's built-in features to find factors with more concise and memory-efficient code.

Simplifying with list comprehension

def find_factors(n):
   return [i for i in range(1, n + 1) if n % i == 0]

print(find_factors(12))--OUTPUT--[1, 2, 3, 4, 6, 12]

List comprehension offers a more "Pythonic" way to build your list of factors. It lets you combine the loop and conditional check into a single, expressive line of code.

  • The expression [i for i in range(1, n + 1) if n % i == 0] directly constructs the list.
  • It still iterates from 1 to n, but it only adds numbers to the list if they satisfy the if condition.

This method is functionally identical to the standard loop but is often favored for its clarity and conciseness.

Yielding factors with a generator function

def find_factors(n):
   for i in range(1, n + 1):
       if n % i == 0:
           yield i

print(list(find_factors(12)))--OUTPUT--[1, 2, 3, 4, 6, 12]

A generator function uses the yield keyword to produce factors one at a time, rather than building a complete list in memory. This approach is significantly more memory-efficient, especially when working with large numbers.

  • The yield i statement pauses the function and sends a factor back to the caller.
  • When the next factor is requested, the function resumes right where it left off.
  • This "lazy evaluation" means you only compute and store one factor at a time.

To see all the factors at once, you can convert the generator's output into a list, as shown with list(find_factors(12)).

Filtering numbers with the filter() function

def is_factor(i):
   return num % i == 0

num = 12
factors = list(filter(is_factor, range(1, num + 1)))
print(factors)--OUTPUT--[1, 2, 3, 4, 6, 12]

The filter() function offers a functional programming approach to finding factors. It pairs a predicate function—one that returns True or False—with an iterable, like a range of numbers.

  • The is_factor function serves as the predicate, checking if a number divides num evenly.
  • filter() applies this function to every number from 1 to num, creating an iterator that contains only the numbers that pass the test (the factors).

Since filter() returns an iterator, you wrap it in list() to get the final list of factors.

Advanced approaches

Building on these foundational methods, you can handle larger numbers far more efficiently by leveraging mathematical properties and specialized Python modules.

Optimizing with mathematical properties

def find_factors(n):
   factors = []
   for i in range(1, int(n**0.5) + 1):
       if n % i == 0:
           factors.append(i)
           if i != n // i:
               factors.append(n // i)
   return sorted(factors)

print(find_factors(12))--OUTPUT--[1, 2, 3, 4, 6, 12]

This method drastically cuts down computation time by recognizing that factors come in pairs. Instead of checking every number up to n, the loop only runs up to the square root of n. This is far more efficient for large numbers.

  • When a factor i is found, its corresponding pair, n // i, is also a factor.
  • The code adds both i and its pair to the list.
  • The check if i != n // i prevents duplicates when n is a perfect square.
  • Finally, sorted() arranges the factors in ascending order.

Leveraging the itertools module

import itertools

def find_factors(n):
   return sorted(set(itertools.chain.from_iterable((i, n // i)
                 for i in range(1, int(n**0.5) + 1) if n % i == 0)))

print(find_factors(12))--OUTPUT--[1, 2, 3, 4, 6, 12]

This approach refines the square root optimization using Python's itertools module for a more compact solution. It generates pairs of factors and then uses itertools.chain.from_iterable() to efficiently flatten them into a single sequence.

  • The itertools.chain.from_iterable() function takes the generated pairs—like (1, 12) and (2, 6)—and chains them into one continuous stream.
  • Wrapping the result in set() is a clever trick that automatically removes any duplicate factors, which can happen with perfect squares.
  • Finally, sorted() arranges the unique factors into a clean, ordered list.

Generating factors from prime factorization

def find_factors(n):
   prime_factors = {}
   d = 2
   while d * d <= n:
       while n % d == 0:
           prime_factors[d] = prime_factors.get(d, 0) + 1
           n //= d
       d += 1
   if n > 1:
       prime_factors[n] = prime_factors.get(n, 0) + 1
   
   factors = [1]
   for prime, power in prime_factors.items():
       factors = [f * prime**p for f in factors for p in range(power + 1)]
   
   return sorted(factors)

print(find_factors(12))--OUTPUT--[1, 2, 3, 4, 6, 12]

This advanced technique works in two stages. First, it performs prime factorization by repeatedly dividing the number n to find its prime factors and their powers, storing them in a dictionary. For 12, this process yields two 2s and one 3.

  • Next, it reconstructs all factors by systematically combining these primes. A nested list comprehension iterates through the collected primes and their powers, multiplying them together to generate every possible divisor.

This method is particularly effective for numbers with many factors.

Move faster with Replit

Replit is an AI-powered development platform that transforms natural language into working applications. Describe what you want to build, and Replit Agent creates it—complete with databases, APIs, and deployment.

For the factor-finding methods we've explored, Replit Agent can turn them into production-ready tools:

  • Build a prime factorization calculator that breaks any number down into its prime components.
  • Create a utility to find the Greatest Common Divisor (GCD) of two numbers, useful for simplifying fractions.
  • Deploy an educational tool that visualizes factor pairs for any given integer to help students learn number theory.

Describe your app idea, and Replit Agent writes the code, tests it, and fixes issues automatically. Try Replit Agent and see how quickly you can bring your concepts to life.

Common errors and challenges

Even robust factor-finding functions can fail with unexpected inputs, so it's wise to prepare for common edge cases.

  • Handling 0 as input: Passing 0 to a factor-finding function can cause issues. While mathematically every non-zero integer is a factor of zero, most algorithms aren't built for this. Your function might return an empty list or, in some cases, trigger a ZeroDivisionError if the logic attempts to divide by zero. A simple check like if n == 0: at the start lets you handle this case gracefully.
  • Dealing with negative numbers: The functions we've discussed will likely return an empty list for negative inputs because range(1, n + 1) is empty when n is negative. Since factors are typically defined as positive integers, a common solution is to work with the number's absolute value by converting it with abs(n).
  • Preventing TypeError with non-integer inputs: Functions like range() and the modulo operator (%) expect integer arguments. If you pass a float or a string to your find_factors() function, Python will raise a TypeError. You can prevent this by validating the input with a type check, such as if not isinstance(n, int):, before the main logic runs.

Handling 0 as input

Passing 0 to a factor-finding function can cause unexpected behavior. While every non-zero integer is technically a factor of zero, most algorithms aren't built for this edge case. You might get an empty list or a runtime error. See what happens with our simple loop function below.

def find_factors(n):
   factors = []
   for i in range(1, n + 1):
       if n % i == 0:
           factors.append(i)
   return factors

print(find_factors(0))

The loop never runs because range(1, 0 + 1) is an empty sequence, so the function returns an empty list. You can add a simple check to handle this case correctly. The following code shows how.

def find_factors(n):
   if n == 0:
       return [0]
   factors = []
   for i in range(1, n + 1):
       if n % i == 0:
           factors.append(i)
   return factors

print(find_factors(0))

The updated find_factors function now handles an input of 0 gracefully. By adding the conditional check if n == 0: at the start, the function immediately returns [0]. This prevents the loop from running on an empty range(1, 1), which would otherwise result in an empty list. It's a simple but crucial fix for ensuring your function is robust against edge cases, especially when dealing with numerical inputs that could be zero.

Dealing with negative numbers in find_factors()

Passing a negative number to find_factors() often returns an empty list because the range(1, n + 1) function becomes an empty sequence. This happens because factors are typically defined as positive integers. See how our simple loop handles this scenario below.

def find_factors(n):
   factors = []
   for i in range(1, n + 1):
       if n % i == 0:
           factors.append(i)
   return factors

print(find_factors(-12))

The loop for i in range(1, -11) never runs because its start value is greater than the end, returning an empty list. The following code demonstrates a simple fix to handle negative inputs correctly.

def find_factors(n):
   n = abs(n)
   factors = []
   for i in range(1, n + 1):
       if n % i == 0:
           factors.append(i)
   return factors

print(find_factors(-12))

The updated find_factors() function now handles negative inputs by converting n to its absolute value with abs(n). This simple change ensures the range() function receives a positive number, allowing the loop to execute correctly and find the factors of the number's positive counterpart. This fix is essential when your function might process unpredictable numerical data, such as from user forms or APIs, preventing it from silently returning an empty list.

Preventing TypeError with non-integer inputs

Your find_factors() function expects an integer. If you pass it a float or string, Python will raise a TypeError because operations like range() and the modulo operator (%) require integers. See how this plays out in the code below.

def find_factors(n):
   factors = []
   for i in range(1, n + 1):
       if n % i == 0:
           factors.append(i)
   return factors

print(find_factors(12.5))

The range() function requires integer arguments, but n + 1 becomes 13.5 when n is a float, which raises a TypeError. The following code shows how to validate the input before the main logic runs.

def find_factors(n):
   if not isinstance(n, int):
       n = int(n)
   factors = []
   for i in range(1, n + 1):
       if n % i == 0:
           factors.append(i)
   return factors

print(find_factors(12.5))

The updated find_factors() function prevents a TypeError by validating the input. It uses isinstance(n, int) to check if the input is an integer. If not, it converts the value to an integer with int(n), which truncates any decimal part. This ensures that functions like range() and the modulo operator (%) receive the integer type they expect. It's a crucial safeguard when your function might receive data from external sources like user input.

Real-world applications

With your functions now hardened against errors, you can confidently apply them to real-world problems like fraction simplification and data analysis.

Simplifying fractions with the gcd() function

A gcd() function leverages factor-finding to identify the Greatest Common Divisor between two numbers, allowing you to simplify fractions to their simplest form.

def gcd(a, b):
   a_factors = set(find_factors(a))
   b_factors = set(find_factors(b))
   common_factors = a_factors.intersection(b_factors)
   return max(common_factors)

def simplify_fraction(numerator, denominator):
   common = gcd(numerator, denominator)
   return numerator // common, denominator // common

print(simplify_fraction(12, 18))

The gcd() function finds the greatest common divisor by comparing the factors of two numbers. It uses sets to make this comparison efficient.

  • First, it calls find_factors() for each number and converts the resulting lists into sets.
  • The intersection() method then creates a new set containing only the factors common to both.
  • Finally, max() returns the largest number from this set of common factors.

The simplify_fraction() function uses this GCD to divide both the numerator and denominator, returning the simplified fraction.

Analyzing factor distribution for numerical data

You can also apply your find_factors() function to analyze patterns in numerical data, like identifying which numbers in a given range have the most divisors.

# Analyze factors for a range of values
factor_counts = {i: len(find_factors(i)) for i in range(1, 21)}

# Find numbers with the most divisors
max_count = max(factor_counts.values())
most_divisible = [n for n, count in factor_counts.items() if count == max_count]
print(f"Numbers with most factors: {most_divisible} ({max_count} factors each)")

This code works in three main steps. First, it uses a dictionary comprehension to create factor_counts, which maps every number from 1 to 20 to its total number of factors.

  • Next, it finds the highest factor count recorded in the dictionary's values using max().
  • Finally, a list comprehension builds the most_divisible list by gathering all numbers from the dictionary that share that same maximum factor count.

Get started with Replit

Turn what you've learned into a real tool. Tell Replit Agent to “build a fraction simplification calculator” or “create a tool that visualizes factor pairs for any integer.”

Replit Agent writes the code, tests for errors, and deploys the app automatically. Start building with Replit to turn your ideas into working software.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.