itertools

itertools is a toolbox of fast, lazy iterator helpers built right into Python. It lets you combine, slice, group, and generate sequences with clean one-liners — and crucially, without loading everything into memory at once.

Learn itertools — Iteration Power Tools in our free Python course — a beginner-friendly interactive lesson with runnable examples, a practice exercise and a…

Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Master a handful of these and your loops get shorter, faster, and far more readable.

Most itertools functions return an iterator , not a list. An iterator produces values one at a time, on demand — it doesn't build the whole sequence up front. That's what makes itertools both fast and memory-light.

chain glues sequences end-to-end into one stream. zip_longest is like the built-in zip but doesn't stop at the shortest input:

Use chain to treat many lists as one without the cost of list1 + list2 + list3 (which copies everything).

You can't slice an iterator with [2:5] . itertools gives you lazy equivalents:

accumulate produces a running result — a cumulative sum by default, or any function you supply. Perfect for running balances and high-water marks:

The last element of a plain accumulate is the same as sum() — but you also get every intermediate step, which is exactly what charts and dashboards need.

groupby groups consecutive equal items. This is the #1 itertools surprise — you almost always sort first:

These replace deeply nested loops with a single readable call:

Reach for product whenever you'd otherwise write nested for loops. Use combinations for "pick a group" and permutations for "arrange in order".

A common reporting task: take a flat list of transactions and produce per-region totals. sort + groupby handles it elegantly:

This same shape — sort, group, aggregate — is the backbone of countless reports. Once it clicks, you'll reach for it constantly.

These lines should print groups of consecutive equal letters, but they're scrambled. Find the order:

This is the perfect groupby use case: the data is already a run of consecutive characters, so no sort is needed. Notice the final 'a' forms its own group.

[1, 2, 3, 4, 5] — chain concatenates the iterables end-to-end into one flat sequence.

[3, 4, 8, 9] — a running sum: 3, 3+1, 3+1+4, 3+1+4+1.

6 — choosing 2 from 4 where order doesn't matter gives 6 pairs: WX, WY, WZ, XY, XZ, YZ.

Your loops just leveled up!

You can chain and zip sequences, slice and filter streams lazily, build running totals with accumulate, group data correctly, and enumerate combinations and permutations. These tools make your code shorter, faster, and clearer.

🚀 Up next: Modern File Paths with pathlib — the clean, object-oriented way to work with files and folders.

Practice quiz

What does list(chain([1, 2], [3], [4, 5])) return?

chain concatenates the iterables end-to-end into one flat sequence.

Why do most itertools functions return iterators instead of lists?

  • They produce values lazily, one at a time, using little memory
  • To sort the data automatically
  • To make the code shorter only
  • Because lists are deprecated

Answer: They produce values lazily, one at a time, using little memory. Lazy iterators yield values on demand, so you can work with huge or infinite sequences cheaply.

What does list(accumulate([3, 1, 4, 1])) return?

accumulate gives a running sum: 3, 3+1, 3+1+4, 3+1+4+1.

What does list(islice([1, 3, 5, 8, 9, 2, 11], 2, 5)) return?

islice(iterable, start, stop) takes indices 2, 3, 4 — the values 5, 8, 9.

What is the key requirement before using groupby?

  • The data must be sorted by the same key, since it only groups consecutive equal items
  • The data must be a dict
  • The data must be numeric
  • The data must be reversed

Answer: The data must be sorted by the same key, since it only groups consecutive equal items. groupby only groups CONSECUTIVE equal elements, so you almost always sort by the key first.

How many pairs does list(combinations("WXYZ", 2)) produce?

  • 4
  • 12
  • 6
  • 16

Answer: 6. Choosing 2 of 4 where order does not matter gives 6 pairs: WX, WY, WZ, XY, XZ, YZ.

When should you use permutations instead of combinations?

  • When you want fewer results
  • When order matters, so (A,B) and (B,A) are distinct
  • When the data is sorted
  • When you need only unique values

Answer: When order matters, so (A,B) and (B,A) are distinct. permutations treats order as significant, producing more results than combinations.

What does takewhile(lambda n: n < 8, [1, 3, 5, 8, 9, 2, 11]) yield?

takewhile takes items while the test is true and STOPS at the first failure (8), giving [1, 3, 5].

How does zip_longest differ from the built-in zip?

  • It sorts the inputs
  • It does not stop at the shortest input and fills gaps with fillvalue
  • It stops at the shortest input
  • It only works on strings

Answer: It does not stop at the shortest input and fills gaps with fillvalue. zip_longest keeps going to the longest input, filling missing positions with fillvalue.

What does product(["S", "M", "L"], ["red", "blue"]) replace?

  • A single sort call
  • A groupby call
  • Nested for loops over the iterables
  • A list comprehension filter

Answer: Nested for loops over the iterables. product yields every combination across the iterables — the flattened result of nested loops (6 pairs here).