Python Combinations vs Permutations: How to Choose
python combinations vs permutations: Understand the difference between Python combinations and permutations, when to use each, and how to avoid common pitfalls.
When you need to generate all possible selections from a collection in Python, the standard library's itertools module provides two closely related tools: combinations and permutations. The difference between python combinations vs permutations comes down to whether order matters. A permutation treats (A, B) and (B, A) as distinct, while a combination treats them as the same selection. That single distinction drives every other difference in syntax, output size, and use case.
What itertools.combinations Produces
The combinations(iterable, r) function yields tuples of length r in lexicographic order, without repeated elements. Each tuple is an unordered selection, meaning the order of elements inside the tuple is not considered significant. The tuples themselves are emitted in a deterministic order based on the input sequence, but (A, B) and (B, A) never both appear.
from itertools import combinations print(list(combinations(['A', 'B', 'C'], 2))) # [('A', 'B'), ('A', 'C'), ('B', 'C')]
The output contains every way to pick two items from three, ignoring order. This is exactly the mathematical definition of a combination.
What itertools.permutations Produces
The permutations(iterable, r=None) function yields all possible orderings of r elements from the input. If r is omitted, it defaults to len(iterable), producing all full-length permutations. Each tuple is an ordered arrangement, so (A, B) and (B, A) are distinct results.
from itertools import permutations print(list(permutations(['A', 'B', 'C'], 2))) # [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]
Notice that the same two elements appear in both orders. This is the key difference from combinations.
Key Differences: Order, Repetition, and Output Size
The most important distinction is order sensitivity. Combinations ignore internal order; permutations do not. Both functions assume the input elements are unique by position, so they do not repeat an element within a single tuple. If you need repetition, you must use combinations_with_replacement or product with repeat.
| Property | combinations | permutations |
|---|---|---|
| Order matters | No | Yes |
| Repetition allowed | No | No |
Output count for n items, r selected | nCr = n! / (r!(n-r)!) | nPr = n! / (n-r)! |
| Typical use | Subsets, teams, lottery picks | Rankings, sequences, arrangements |
The count difference is dramatic. For n=10 and r=4, there are 210 combinations but 5040 permutations. As n and r grow, permutations explode much faster.
Choosing the Right Function for Your Problem
Your choice depends entirely on whether the order of the selected items changes the outcome. If you are selecting a committee from a list of people, the order of selection does not matter, so use combinations. If you are generating possible passwords from a set of characters, the order matters, so use permutations.
Consider a scenario where you need to assign three distinct roles (president, treasurer, secretary) from five candidates. Since each role is different, permutations(candidates, 3) is correct. If you only need to choose three people to form a team, combinations(candidates, 3) is the right tool.
A common mistake is using permutations when the problem is actually about subsets. Ask yourself: would swapping two selected items produce a different valid result? If not, you need combinations.
Performance and Memory Considerations
Both functions return lazy iterators, so they generate tuples one at a time. This is memory-efficient for iteration, but the total number of results can become impractical. The output size grows factorially for permutations and polynomially for combinations. For even moderate input sizes, materializing the full result into a list can exhaust memory.
from itertools import permutations # n=10, r=10 -> 3,628,800 tuples for perm in permutations(range(10)): # process each permutation pass
This loop will run 3.6 million times, which is fine if the body is cheap, but you should avoid storing all results unless you know the count is manageable. The memory per tuple is proportional to r, but the number of tuples dominates. Prefer streaming processing over list() when the count is large.
Common Mistakes and Edge Cases
Several edge cases trip up developers new to these functions.
rgreater thann: Both functions return an empty iterator. This is often unexpected but correct.requal to zero: Both return a single empty tuple. This matches the mathematical convention that there is exactly one way to choose nothing.- Duplicate elements in the input:
itertoolstreats each element by its position, not its value. If your input contains duplicate values, the output will contain duplicate tuples. Useset()on the input or on the output to deduplicate, but be aware that this changes the count and may be expensive. - Forgetting that
permutationswithromitted useslen(iterable): This producesn!results, which can be enormous even for smalln. Always specifyrunless you truly need all full-length permutations.
Related Tools: combinations_with_replacement and product
When repetition is allowed, the standard combinations and permutations are insufficient. combinations_with_replacement(iterable, r) allows the same element to appear multiple times in a tuple, but still ignores order. For example, selecting two scoops of ice cream from five flavors where you can pick the same flavor twice is a combination with replacement.
from itertools import combinations_with_replacement print(list(combinations_with_replacement(['A', 'B', 'C'], 2))) # [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
For ordered selections with repetition, use product(iterable, repeat=r). This produces the Cartesian product, which is the same as permutations with replacement.
from itertools import product print(list(product(['A', 'B'], repeat=2))) # [('A', 'A'), ('A', 'B'), ('B', 'A'), ('B', 'B')]
Understanding these four functions gives you complete coverage of ordered and unordered selections with and without repetition.
A Practical Decision Rule
When you face a selection problem, apply this rule in order. First, determine whether repetition is allowed. If yes, use combinations_with_replacement for unordered selections or product for ordered ones. If no, check whether order matters. If order matters, use permutations; if not, use combinations. This simple branching logic covers the vast majority of combinatorics problems in Python. For example, generating all possible 4-digit PINs from digits 0-9 is product(range(10), repeat=4) because order matters and repetition is allowed. Selecting a hand of 5 cards from a deck is combinations(deck, 5) because order does not matter and repetition is impossible. Keeping this decision tree in mind prevents the most common misuse of these powerful iterators.