Quick answer: itertools.combinations yields r-length selections of an iterable without replacement. It is lazy and preserves input-position order, but the number of possible results can still grow combinatorially, so choose r and consumption strategy carefully.

itertools.combinations() returns fixed-length selections from an iterable. Each result is a tuple, order inside the input is preserved, and the same input position is not reused within one combination.
Use it when order does not matter. For example, choosing two team members from a group is a combination problem because ("Ana", "Bo") and ("Bo", "Ana") represent the same pair.
The official Python itertools.combinations documentation defines the function and its result order. The official combinations_with_replacement documentation covers the related form that can reuse input positions.
Create Basic Combinations
Pass an iterable and the desired length r. Convert the iterator to a list only when the result is small enough to hold in memory.
from itertools import combinations
letters = ["A", "B", "C"]
pairs = list(combinations(letters, 2))
print(pairs)
The output contains ("A", "B"), ("A", "C"), and ("B", "C"). It does not include reversed duplicates.
The original input order controls the tuple order and the order in which combinations are produced.
Choose Different Lengths
The second argument controls how many items appear in each tuple.
from itertools import combinations
items = ["red", "green", "blue", "black"]
for size in [2, 3]:
print(size, list(combinations(items, size)))
A size of two creates pairs. A size of three creates triples. If r is larger than the input length, the iterator produces no results.
This makes the function useful for menus, feature selection, test cases, pairing tasks, and any workflow that needs all unordered selections of a fixed size.
Allow Repeated Items
Use combinations_with_replacement() when the same input item can appear more than once in a result.
from itertools import combinations_with_replacement
scores = [1, 2, 3]
choices = list(combinations_with_replacement(scores, 2))
print(choices)
This includes pairs such as (1, 1) and (2, 2), which normal combinations() would not produce from a single input position.
Use the replacement form for problems such as repeated choices, dice-like outcomes where order is ignored, or selecting categories where the same category can be chosen more than once.

Count Results Before Building Them
The number of combinations grows quickly. Use math.comb() to estimate the result count before materializing a large list.
from itertools import combinations
from math import comb
people = range(30)
group_size = 4
print(comb(len(people), group_size))
first_group = next(combinations(people, group_size))
print(first_group)
For 30 choose 4, the count is already large. Converting the whole iterator to a list may waste memory when you only need to loop over results.
Prefer streaming with a for loop when the output could be large.
Filter Combination Results
Often you generate combinations and then keep only those that satisfy a condition.
from itertools import combinations
numbers = [2, 4, 5, 8, 11]
for pair in combinations(numbers, 2):
if sum(pair) >= 13:
print(pair)
This keeps the code readable: combinations() handles selection, and the if statement handles the business rule.
For expensive checks, stop early whenever possible. Combination counts can grow faster than expected.

Preview Large Iterators
Use islice() to inspect only the first few results without building the whole sequence.
from itertools import combinations, islice
labels = [f"item-{index}" for index in range(10)]
preview = list(islice(combinations(labels, 3), 5))
print(preview)
This is useful in notebooks, debug output, and tests where the complete result would be too large to display.
Compare Related itertools Tools
combinations(), permutations(), and product() answer different questions. Choose the tool based on whether order matters and whether items can be reused.
Use combinations() when order does not matter and each input position can appear at most once. Use permutations() when order matters. Use product() when choosing one item from each input collection or when repeated positions are part of the problem.
A common mistake is to use permutations and then remove duplicates later. That does extra work and makes the intent less clear. If reversed pairs mean the same thing, start with combinations.
Another mistake is assuming equal values are collapsed. combinations() works by input position, not by unique value. If the input contains duplicate values, the output can contain duplicate-looking tuples. Deduplicate the input first when unique values are required.
For large data, avoid wrapping the result in list() during normal processing. A lazy iterator lets you process one tuple at a time and stop early when enough results have been found.
Before using the function, decide three things: the selection size, whether repeated positions are allowed, and whether order changes the meaning. Those answers identify the right itertools helper and prevent accidental extra work. Combinations ignore order, while Python Permutations With itertools generates ordered arrangements and explains repeated inputs and result counts.
The practical rule is to use combinations() for unordered selections without replacement, combinations_with_replacement() when reuse is allowed, and math.comb() when you need the count before deciding whether to build results.
Keep large combination sets lazy whenever possible. Iterating over the generator is usually better than creating a massive list.
Understand Positions
Combinations select distinct input positions and do not repeat a position within one result. Equal values at different positions can therefore appear in separate combinations.

Choose r
When r is zero, the iterator yields one empty tuple; when r is larger than the input length, it yields nothing. Make that boundary part of the contract.
Use Lazy Consumption
The iterator avoids allocating every result at once. Do not convert it to a list unless the result count and memory budget are known.

Estimate The Count
For n inputs and r selected positions, the count is n choose r. Estimate it before collecting, sending, or displaying all results.
Compare Related Tools
Use combinations_with_replacement when repeated values are allowed, permutations when order matters, and product for Cartesian choices.
Test Ordering And Values
Test empty and short inputs, r=0, r=1, r=n, r>n, duplicate values, generator inputs, ordering, and partial consumption.
Use the official itertools combinations documentation. Related Python Pool references include lists and testing.
For related sequence workflows, compare list materialization, iterator tests, and count mappings before consuming combinations.
Frequently Asked Questions
What does itertools.combinations do?
It yields subsequences of a chosen length r from the input iterable without repeating positions.
Are combinations ordered?
The output follows the input order of positions, and each combination is emitted in lexicographic order relative to that input.
How many combinations are generated?
For n input items and r selected positions, the count is n choose r when 0 <= r <= n.
Does combinations return a list?
No. It returns an iterator, so values are generated lazily until consumed or converted into a collection.