skip to content

What is the difference between itertools.permutations and itertools.combinations?

level: juniorimportance: must knowfreq 62%

answer

  1. One cares about arrangement, one does not
  2. Three letters, pairs: six versus three
  3. r! permutations per single combination
  4. math.perm and math.comb count without iterating
  5. Selection is positional, never by value

basics

~20 s

itertools.permutations treats order as significant, so ('a','b') and ('b','a') are both yielded. itertools.combinations yields each selection once, keeping the input's own order. For n items taken r at a time that is n!/(n-r)! tuples versus n!/(r!(n-r)!).

solid answer

~40 s

Both take an iterable and a length `r` and yield tuples lazily, but they differ on whether arrangement counts. `itertools.permutations('abc', 2)` yields six tuples, including both `('a','b')` and `('b','a')`, because it enumerates ordered arrangements. `itertools.combinations('abc', 2)` yields three — `('a','b')`, `('a','c')`, `('b','c')` — one per unordered selection, always emitting the chosen elements in the order they appeared in the input. The counts are the familiar formulas: n!/(n-r)! for permutations and n!/(r!(n-r)!) for combinations, computable without running anything via `math.perm` and `math.comb`. Both select by position rather than by value, so neither deduplicates equal elements. Reach for combinations when the result is a set-like choice (which two servers to drain) and permutations when the arrangement itself is the answer (in which order to visit them).

code

python · 5 lines
python
from itertools import permutations, combinations

items = ["a", "b", "c"]
print(list(permutations(items, 2)))
print(list(combinations(items, 2)))

go deeper

for a junior

Recall that permutations counts orderings and combinations does not, and be able to write both calls for a three-letter string and say how many tuples each returns.

for a middle

Explain the two count formulas, that output order mirrors input order rather than being sorted, and that both select by position so equal elements produce duplicate tuples.

for a senior

Show the instinct to size the enumeration with math.perm or math.comb before iterating, and explain that laziness bounds memory but never runtime.

for a principal

Frame the choice as a modelling decision: picking permutations where combinations was meant multiplies the work by r! and silently returns rearrangements as if they were distinct results.

### The two questions they answer Every combinatorial enumeration starts with one decision: **does the arrangement of the chosen elements matter?** `itertools.permutations` says yes; `itertools.combinations` says no. Everything else about the two functions — their signatures, their laziness, their ordering, their output counts — follows from that single distinction. Both have the shape `f(iterable, r=None)`. They pull the whole input into an internal tuple up front, then yield tuples of length `r` one at a time. For `permutations`, `r` defaults to the full length of the input; `combinations` requires `r` explicitly. ```python from itertools import permutations, combinations items = ['a', 'b', 'c'] list(permutations(items, 2)) # [('a','b'), ('a','c'), ('b','a'), ('b','c'), ('c','a'), ('c','b')] list(combinations(items, 2)) # [('a','b'), ('a','c'), ('b','c')] ``` The permutation list contains three extra tuples: each combination appears in both of its orderings. In general each combination of size r corresponds to r! permutations, which is exactly why the two count formulas differ by that factor. ### The counts, and why they matter more than the API For n input elements taken r at a time: * permutations: n! / (n - r)! — the number of ordered arrangements. * combinations: n! / (r! (n - r)!) — the binomial coefficient, usually written C(n, r). The standard library will compute both for you without generating anything: `math.perm(n, r)` and `math.comb(n, r)`. This is the habit worth forming — before writing a loop over one of these iterators, evaluate its size. `math.comb(52, 5)` is 2,598,960, a fine thing to iterate. `math.perm(20, 20)`, which is 20!, is about 2.4 x 10^18, and no amount of laziness makes that loop terminate. ### Ordering of the output Neither function sorts. Both walk index positions of the internal input tuple in increasing order, so the output order is a function of **input order**, not of value. If the input is already sorted, the output tuples come out in lexicographic order — which is why textbook examples always look sorted. Feed unsorted input and you get unsorted output, in a completely deterministic order that mirrors the input's own sequence. A direct consequence: **selection is positional, not value-based.** If the input contains equal elements, the output contains equal tuples. `combinations(['a','a','b'], 2)` yields `('a','a')`, `('a','b')` and `('a','b')` — two identical pairs, because the two `'a'` values sit at different positions. Neither function has any notion of a set. ### Laziness and memory Both return iterators, so nothing is precomputed: memory is the input tuple plus one output tuple plus a small array of indices. That means the memory cost is trivial even for astronomically large enumerations — and it is precisely why the runtime trap is so easy to fall into. Laziness bounds memory, never time. A `for` loop over `permutations` of twenty things will still be running long after everyone has gone home. Because the input is drained into a tuple immediately, passing a generator to either function consumes it in full before the first tuple is yielded, and passing an endless iterator hangs at construction rather than at the first `next()`. ### Choosing between them The test is a sentence: read the problem statement and ask whether swapping two chosen elements produces a different answer. * Which two of these five fee codes appear together on the same invoice? Order is meaningless — `combinations`. * In what sequence do we apply three discounts to a line item? Order changes the total — `permutations`. * Every possible assignment of one of three tiers to each of four accounts? That is neither: it is a Cartesian product, `itertools.product` with `repeat=4`. Getting this wrong is a silent bug, not a crash: an enumeration using `permutations` where `combinations` was meant simply does r! times the work and reports duplicated results that differ only in arrangement, which is easy to miss when the downstream code aggregates. ### Interview framing Interviewers ask this as a screen because it merges three things a working engineer needs: knowing the stdlib exists rather than hand-rolling recursion, recalling the two counting formulas, and having the instinct to estimate the output size before iterating it. A complete answer names both functions, shows a three-element example, states both formulas, and adds that the output order follows input order and that neither deduplicates.

  • How many tuples does itertools.permutations(range(10), 3) yield, and how would you work that out without running it?
    720 — that is 10!/(10-3)! = 10 x 9 x 8. `math.perm(10, 3)` returns it directly, and `math.comb(10, 3)` returns 120, the same enumeration with order ignored; the ratio is 3! = 6. Computing the count first is the habit that stops an enumeration from being started and then abandoned.
  • What does itertools.permutations do when you omit the second argument?
    `r` defaults to the full length of the input, so it yields every full-length arrangement — n! tuples. That default is a common accident: `permutations(items)` on a ten-element list is 3,628,800 tuples, while the author usually meant pairs. `itertools.combinations` has no such default and requires `r`.
  • Do either of these functions remove duplicate results when the input contains equal elements?
    No. Both select by position, not by value, so equal input elements produce equal output tuples. `combinations(['a','a','b'], 2)` yields `('a','b')` twice. If you need distinct results, deduplicate the input first, or collect the output into a set — accepting that the enumeration still does the full amount of work.

Combinations are who you invite to dinner; permutations are where each guest sits. The same guest list seats many different ways.

saying these in an interview costs you the question

  • Says combinations sorts its output regardless of input order
  • Claims either function deduplicates equal input elements
  • Thinks permutations and combinations yield the same number of tuples
  • Believes laziness makes a factorial enumeration cheap to run
  • Confuses combinations with the Cartesian product of several iterables
  • Cannot state either count formula even approximately

context