-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
176: The itertools Module: combinations and permutations
A few years ago, I was helping a colleague build a small tool for a local esports league. They needed to generate a schedule for a round-robin tournament where every team played every other team exactly once. I watched them struggle for an hour writing nested for loops, trying to figure out how to avoid "Team A vs Team A" and how to prevent "Team A vs Team B" from being listed separately from "Team B vs Team A." The code was becoming a jungle of if statements and index offsets.
It's a classic trap. When we think about "every possible pair" or "every possible ordering," our instinct is to reach for nested loops. But the moment you need a group of three or four, or the moment the order of those items starts to matter, your logic collapses under its own weight. This is exactly why the itertools module exists. It handles the combinatorial math under the hood so you can focus on what to do with the results.
Generating Unique Pairings with combinations
When the order of the items doesn't matter—meaning a pair of {Alice, Bob} is the same thing as {Bob, Alice}—you want itertools.combinations. This is what my colleague needed for the tournament matchups. You provide an iterable and a length r, and Python yields every possible unique subset of that length.
from itertools import combinations
teams = ['Dragons', 'Knights', ' Wizards', 'Titans']
# We want pairs (2 teams per match)
matchups = list(combinations(teams, 2))
for match in matchups:
print(f"{match[0]} vs {match[1]}")
Notice that we don't get "Dragons vs Dragons" and we don't get both "Dragons vs Knights" and "Knights vs Dragons." It's clean, it's efficient, and it's far more readable than a manual loop. One thing to keep in mind: combinations returns an iterator. If you need to access the results multiple times or know the total count immediately, you'll need to cast it to a list, though for large datasets, iterating over it directly is much kinder to your RAM.
Handling Sequence and Rank with permutations
Now, there are times when the order does matter. If we aren't talking about who is playing whom, but rather who wins Gold, Silver, and Bronze, then {Alice, Bob, Charlie} is a very different outcome than {Charlie, Bob, Alice}. For this, we use itertools.permutations.
Permutations generate every possible arrangement. If you have four teams and you want to see every possible way the top three spots could be filled, the number of results grows much faster than it does with combinations.
from itertools import permutations
players = ['Alice', 'Bob', 'Charlie', 'Diana']
# Top 3 finishers: Gold, Silver, Bronze
podiums = list(permutations(players, 3))
print(f"Total possible outcomes: {len(podiums)}")
# Example output: ('Alice', 'Bob', 'Charlie'), ('Alice', 'Bob', 'Diana'), etc.
I usually tell people to be careful with permutations. Because it considers order, the number of results can explode (factorial growth). If you accidentally run a permutation on a list of 20 items without a small r value, you're going to hang your program. Always double-check if the order actually changes the meaning of your data before choosing this over combinations.
📋 Practical Task
The Tournament Pairing and Podium Generator
You are tasked with creating a utility for a chess club. The club has a list of players, and they need two things: a list of all unique matches for their "Friendly Friday" round-robin and a list of all possible ways the top two players could finish (First and Second place) for their trophy ceremony.
Write a script that does the following:
- Create a list called
playerscontaining:"Magnus", "Hikaru", "Fabiano", "Ian". - Use
itertools.combinationsto generate all unique pairings of 2 players. Print these as:"Match: [Player 1] vs [Player 2]". - Use
itertools.permutationsto generate all possible ways these players could take 1st and 2nd place. Print these as:"1st: [Player 1], 2nd: [Player 2]".
There are no comments for now.