Python

P
PythonHub
Progress 0%

Python

  • Home
  • History of Python
  • Applications of Python
  • Introduction To Python
    • What is Python
    • Character Set
    • Tokens in Python
    • Python Execution Mode
    • Variable And Identifiers
    • Data Types in Python
    • Operators And Expressions
    • Constants in Python
    • Assignment Statement
    • Input / Output in Python
    • Simple Python Scripts
    • Namespace in Python
    • 📝 Assignments
  • Operators in Python
    • Arithmetic Operators
    • Assignment Operators
    • Shorthand Assignment Operators
    • Relational Operators
    • Logical Operators
    • Bitwise Operators
    • Special Operators
    • 📝 Assignments
  • Input Output in Python
    • Accept Input
    • Output Formatting
    • 📝 Assignments
  • Conditional Statement
    • Decision Making
    • if Statement
    • IF-ELSE STATEMENT
    • IF-ELSE LADDER
    • NESTED IF-ELSE
    • Short Hand IF-ELSE
    • 📝 Assignments
  • Loops
    • Introduction to Loops
    • While Loop
    • Nested While Loop
    • 📝 While Loop Assignments
    • For Loop
    • For Loop Examples
    • Nested For Loop
    • Nested For Loop Examples
    • Infinite While Loops
    • Infinite For Loops
    • Break, Continue and Else in Loops
    • Difference Between For and While Loop
    • For Each Loop
    • 📝 For Each Assignments
    • 📝 All Loops Assignments
  • List
    • List in Python
    • Access List Elements
    • List Functions
    • Iterate (Loop) List
    • List Comprehension
    • 📝 Assignments
  • Tuple
    • Tuple in Python
    • Access Tuple Elements
    • Tuple Functions
    • Iterate (Loop) Tuple
    • Unpack Tuple
    • Tuple Comprehension
    • 📝 Assignments
  • Set
    • Set in Python
    • Access Set Elements
    • Set Methods
    • Iterate (Loop) Set
    • Pack/Unpack Set
    • Set Comprehension
    • 📝 Assignments
  • Dictionary
    • Dictionary
    • Access Dictionary Items
    • Dictionary Methods
    • Iterate (Loop) Dictionary
    • Formatting Dictionaries
    • Nested Dictionaries
    • Dictionary Comprehension
    • 📝 Assignments
  • Diff List Tuple Set Dictionary
    • List vs Tuple
    • List vs Set
    • List vs Dictionary
    • Tuple vs Set
    • Tuple vs Dictionary
    • Dictionary vs Set
    • 📝 Assignments
  • Exception
    • Error vs Exception
    • Types of Exception
    • Exception Handling
    • User Defined Exception
    • Logging Exception
    • 📝 Assignments
  • Functions
    • Introduction to Functions
    • Modular Programming
    • Types of Functions
    • Inbuilt Functions
    • Need For User-Defined Function
    • Elements of User Defined Function
    • Function Arguments
    • Nesting of Functions
    • Recursion
    • Global Local and Non Local
    • Python Lambda Functions
    • 📝 Assignments
  • Python Module
    • Introduction to Module
    • Inbuilt Modules in Python
    • User Defined Module
    • 📝 Assignments
  • File Handling
    • Introduction to Files
    • Create File
    • Read Files
    • Write to File
    • Rename File
    • Copy File
    • Move File
    • List Files in Directory
    • Binary Files
    • Zipping and Unzipping Files
    • 📝 Assignments
  • Strings
    • Basics of Strings
    • String Special Operators
    • String Formatting Operators
    • String Methods
    • 📝 Assignments
  • Regular Expressions
  • Python OOPS
    • Basics of Object Oriented
    • What are Classes and Objects?
    • Creating Class and Object
    • OOP vs Procedural Programming
    • Difference Between Classes and Objects
    • Constructors
    • Destructor
    • Built Class Methods and Attributes
    • Class and Instance Variables
    • Inheritance in Python
    • Single Inheritance
    • Multiple Inheritance
    • Multilevel Inheritance
    • Hierarchical Inheritance
    • Hybrid Inheritance
    • Abstraction
    • Method Overriding
    • Abstract Method
    • Interfaces in Python
    • Abstract Class vs Interface
    • Public, Private and Protected
    • Overloading vs Overriding
    • Inheritance vs Composition
    • Encapsulation
    • Polymorphism
    • Inner Classes
    • 📝 Assignments
  • Advanced Python
    • Iterator in Python
    • Generator in Python
    • Decorator in Python
    • Type Hints in Python
    • Async/Await Programming
    • Dataclasses in Python
    • Context Managers in Python
    • Property Decorator in Python
    • __slots__ in Python
    • Enums in Python
    • Walrus Operator in Python
    • Match-Case in Python
    • 📝 Assignments
  • Python Standard Library
    • Collections Module
    • Itertools Module
    • Functools Module
    • Datetime Module
    • JSON Module
    • OS Module
    • Sys Module
    • Random Module
    • Math Module
    • 📝 Assignments
  • Python Testing
    • Unit Testing in Python
    • Pytest Framework
    • Mocking in Python
    • 📝 Assignments
  • Python Best Practices
    • PEP 8 Style Guide
    • Docstrings in Python
    • Logging in Python
    • Code Optimization Tips
    • Debugging Techniques
    • 📝 Assignments
  • MySQL Database in Python
    • Introduction to MySQL with Python
    • DBMS vs File System
    • Connecting to MySQL Database
    • Create Database in MySQL
    • Create Table in MySQL
    • Insert Data in MySQL
    • Insert Multiple Rows
    • Select Data from MySQL
    • WHERE Clause in MySQL
    • Update Data in MySQL
    • Delete Data from MySQL
    • Parameterized Queries
    • Transaction Management
    • Error Handling
    • Connection Pooling
    • MySQL Drivers Guide
    • Joins in MySQL
    • Aggregation Functions
    • Backup MySQL Database
    • Best Practices
    • 📝 Assignments
  • MySQL Database Operations
    • SELECT Statement
    • MySQL Operators
    • DDL Statements
    • DML Statements
    • Subqueries
    • JOIN Operations
    • Aggregation
    • Case Study
    • 📝 Assignments
  • Graphics in Python
  • Threads in Python
    • Introduction to Threads
    • Process vs Threads
    • Concurrent Programming & GIL
    • Uses of Threads
    • Creating Threads
    • Single Tasking
    • Multi Tasking
    • Thread Synchronization
    • 📝 Assignments
  • Interview Questions & Answers
  • Python Case Studies
  • Multiple Choice Questions
  • 📝 Practice Problems
Get in Touch
  • tech2dsm@gmail.com

© Sankalan Data Tech

Python Language Interactive Tutorial

Python: Itertools Module

Python Itertools Module - Complete Guide

Powerful tools for working with iterators and sequences.

Created by Sankalan Data Tech Team Verified
Data Engineers, Analysts, Scientists & Trainers
Created by experienced Python developers, data engineers, and data scientists to make programming easy through practical examples, real-world experience, and clear explanations.
On this page:
  • What is Itertools?
  • Infinite Iterators
  • Finite Iterators
  • Combinatoric Generators
  • Grouping with groupby
  • Real-World Example
  • Best Practices
  • Try It Yourself
  • Quick Quiz
  • Frequently Asked Questions
Share this tutorial:
Twitter LinkedIn Facebook WhatsApp Reddit Telegram Email Copy Link
What You'll Learn Here
  • What is itertools — a module for advanced iteration
  • Infinite iterators — count, cycle, repeat
  • Finite iterators — chain, zip_longest, islice
  • Combinatoric generators — product, permutations, combinations
  • Grouping — groupby for grouping data

What is Itertools?

The itertools module is a collection of tools for working with iterators. It provides fast, memory-efficient functions that make complex iteration tasks simple and clean.

Think of itertools like a Swiss Army knife for loops and iterators. It has specialized tools for common iteration patterns that would otherwise require writing complex code.

All functions in itertools return iterators (generators), which means they are memory-efficient and lazy. They only produce values as you consume them.

💡 Key concept: Itertools provides powerful, memory-efficient tools for working with iterators and sequences.

Infinite Iterators

1

count, cycle, repeat

These iterators never stop producing values. You need to stop them with a limit.

# Infinite Iterators - count, cycle, repeat

from itertools import count, cycle, repeat
import itertools

print("=" * 50)
print("INFINITE ITERATORS")
print("=" * 50)

# ============================================================
# 1. count - Count from a starting number
# ============================================================

print("\n1. count() - Count from a starting number")

# Count from 5
counter = count(5)
print("   First 5 numbers from count(5):")
for i, num in enumerate(counter):
    if i >= 5:
        break
    print(f"      {num}")

# Count with step
counter = count(10, 3)
print("   First 5 numbers from count(10, 3):")
for i, num in enumerate(counter):
    if i >= 5:
        break
    print(f"      {num}")


# ============================================================
# 2. cycle - Cycle through a sequence forever
# ============================================================

print("\n2. cycle() - Cycle through a sequence")

colors = cycle(["red", "green", "blue"])
print("   First 7 colors from cycle:")
for i, color in enumerate(colors):
    if i >= 7:
        break
    print(f"      {color}")


# ============================================================
# 3. repeat - Repeat a value forever or n times
# ============================================================

print("\n3. repeat() - Repeat a value")

# Repeat forever
repeater = repeat("Hello")
print("   First 3 repeats:")
for i, word in enumerate(repeater):
    if i >= 3:
        break
    print(f"      {word}")

# Repeat n times
repeater = repeat("World", 5)
print("   Repeat 'World' 5 times:")
for word in repeater:
    print(f"      {word}")


# ============================================================
# 4. Using islice to limit infinite iterators
# ============================================================

print("\n4. Using islice() to limit infinite iterators")

from itertools import islice

# Take first 5 from infinite counter
first_five = list(islice(count(100, 2), 5))
print(f"   First 5 from count(100, 2): {first_five}")

# Take 3 from cycle
three_colors = list(islice(cycle(["A", "B", "C"]), 3))
print(f"   First 3 from cycle: {three_colors}")

Infinite iterators key points:

  • count() — counts from a starting number with a step
  • cycle() — cycles through a sequence forever
  • repeat() — repeats a value forever or n times
  • islice() — limits infinite iterators

Quick Check: How do you limit an infinite iterator? (Answer: Use itertools.islice())

Finite Iterators

2

chain, zip_longest, islice

These iterators work on finite sequences and stop when the input is exhausted.

# Finite Iterators

from itertools import chain, zip_longest, islice, compress, dropwhile, takewhile, filterfalse
import itertools

print("=" * 50)
print("FINITE ITERATORS")
print("=" * 50)

# ============================================================
# 1. chain - Combine multiple iterables
# ============================================================

print("\n1. chain() - Combine iterables")

list1 = [1, 2, 3]
list2 = [4, 5, 6]
list3 = [7, 8, 9]

chained = chain(list1, list2, list3)
print(f"   chain({list1}, {list2}, {list3}): {list(chained)}")

# Chain with * operator
data = [[1, 2], [3, 4], [5, 6]]
flat = chain(*data)
print(f"   chain(*{data}): {list(flat)}")


# ============================================================
# 2. zip_longest - Zip with fill value
# ============================================================

print("\n2. zip_longest() - Zip with fill value")

names = ["Alice", "Bob", "Charlie"]
ages = [25, 30]
scores = [95, 87, 92, 100]

# Regular zip stops at shortest
regular = list(zip(names, ages, scores))
print(f"   Regular zip: {regular}")

# zip_longest fills missing values
longest = list(zip_longest(names, ages, scores, fillvalue="N/A"))
print(f"   zip_longest: {longest}")


# ============================================================
# 3. islice - Slice an iterator
# ============================================================

print("\n3. islice() - Slice an iterator")

data = range(20)
print(f"   Range 0-19: {list(range(20))}")

# First 5
first5 = list(islice(data, 5))
print(f"   First 5: {first5}")

# From 5 to 9
middle = list(islice(range(20), 5, 10))
print(f"   Middle 5-9: {middle}")

# Every 3rd from 2 to 14
step = list(islice(range(20), 2, 15, 3))
print(f"   Every 3rd from 2 to 14: {step}")


# ============================================================
# 4. compress - Filter by selector
# ============================================================

print("\n4. compress() - Filter by selector")

letters = ['A', 'B', 'C', 'D', 'E']
selectors = [True, False, True, False, True]

selected = compress(letters, selectors)
print(f"   compress({letters}, {selectors}): {list(selected)}")


# ============================================================
# 5. dropwhile and takewhile
# ============================================================

print("\n5. dropwhile() and takewhile()")

numbers = [1, 3, 5, 7, 2, 4, 6, 8]

# dropwhile - drop until condition is False
dropped = list(dropwhile(lambda x: x < 5, numbers))
print(f"   dropwhile(<5): {dropped}")

# takewhile - take until condition is False
taken = list(takewhile(lambda x: x < 5, numbers))
print(f"   takewhile(<5): {taken}")


# ============================================================
# 6. filterfalse - Opposite of filter
# ============================================================

print("\n6. filterfalse() - Opposite of filter")

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Regular filter - keeps True
even = list(filter(lambda x: x % 2 == 0, numbers))
print(f"   filter(even): {even}")

# filterfalse - keeps False
odd = list(filterfalse(lambda x: x % 2 == 0, numbers))
print(f"   filterfalse(even): {odd}")

Finite iterators key points:

  • chain() — combine multiple iterables
  • zip_longest() — zip with fill value
  • islice() — slice an iterator
  • compress() — filter by selector
  • dropwhile/takewhile — filter based on condition

Quick Check: What's the difference between zip and zip_longest? (Answer: zip stops at the shortest iterable, zip_longest fills missing values)

Combinatoric Generators

3

product, permutations, combinations

These generators create all possible combinations and arrangements of items.

# Combinatoric Generators

from itertools import product, permutations, combinations, combinations_with_replacement

print("=" * 50)
print("COMBINATORIC GENERATORS")
print("=" * 50)

# ============================================================
# 1. product - Cartesian product
# ============================================================

print("\n1. product() - Cartesian product")

# Product of two lists
colors = ['red', 'blue']
sizes = ['S', 'M', 'L']
products = list(product(colors, sizes))
print(f"   product({colors}, {sizes}):")
for p in products:
    print(f"      {p}")

# Product with repetition
combs = list(product([1, 2], repeat=2))
print(f"   product([1, 2], repeat=2): {combs}")


# ============================================================
# 2. permutations - All orderings
# ============================================================

print("\n2. permutations() - All orderings")

items = ['A', 'B', 'C']

# All permutations of length 2
perms = list(permutations(items, 2))
print(f"   permutations({items}, 2): {perms}")

# All permutations of full length
perms_full = list(permutations(items))
print(f"   permutations({items}): {perms_full}")


# ============================================================
# 3. combinations - All combinations (order doesn't matter)
# ============================================================

print("\n3. combinations() - Combinations")

items = ['A', 'B', 'C', 'D']

# All combinations of length 2
combs = list(combinations(items, 2))
print(f"   combinations({items}, 2): {combs}")

# All combinations of length 3
combs3 = list(combinations(items, 3))
print(f"   combinations({items}, 3): {combs3}")


# ============================================================
# 4. combinations_with_replacement - Combinations with repetition
# ============================================================

print("\n4. combinations_with_replacement() - With repetition")

items = ['A', 'B', 'C']

# With repetition allowed
combs = list(combinations_with_replacement(items, 2))
print(f"   combinations_with_replacement({items}, 2): {combs}")


# ============================================================
# 5. COMPARISON
# ============================================================

print("\n5. COMPARISON")

print("""
┌──────────────────────┬────────────────────────────────────────────┐
│ FUNCTION             │ WHAT IT DOES                              │
├──────────────────────┼────────────────────────────────────────────┤
│ product              │ All combinations (with repetition)        │
│                      │ Order matters                             │
│                      │                                            │
│ permutations         │ All arrangements (order matters)          │
│                      │ No repetition                             │
│                      │                                            │
│ combinations         │ All selections (order doesn't matter)     │
│                      │ No repetition                             │
│                      │                                            │
│ combinations_with    │ All selections (order doesn't matter)     │
│ _replacement         │ Repetition allowed                        │
└──────────────────────┴────────────────────────────────────────────┘
""")

Combinatoric generators key points:

  • product() — Cartesian product (all combinations)
  • permutations() — all orderings (order matters)
  • combinations() — all selections (order doesn't matter)
  • combinations_with_replacement() — with repetition

Quick Check: What's the difference between permutations and combinations? (Answer: Permutations care about order, combinations don't)

Grouping with groupby

4

Group Data Like a Pro

groupby is a powerful function that groups consecutive items in a sequence based on a key function.

# Grouping with groupby

from itertools import groupby

print("=" * 50)
print("GROUPBY - GROUPING DATA")
print("=" * 50)

# ============================================================
# 1. BASIC GROUPBY
# ============================================================

print("\n1. BASIC GROUPBY")

# Data must be sorted by the grouping key!
data = ["apple", "banana", "apple", "apple", "banana", "cherry"]
sorted_data = sorted(data)

print(f"   Original: {data}")
print(f"   Sorted: {sorted_data}")

# Group by the item itself
groups = groupby(sorted_data)
for key, group in groups:
    print(f"      {key}: {list(group)}")


# ============================================================
# 2. GROUPING BY A FUNCTION
# ============================================================

print("\n2. GROUPING BY A FUNCTION")

# Group words by their first letter
words = ["apple", "apricot", "banana", "blueberry", "cherry", "coconut"]
sorted_words = sorted(words)  # Must be sorted by the key

groups = groupby(sorted_words, key=lambda x: x[0])
for letter, group in groups:
    print(f"      {letter}: {list(group)}")


# ============================================================
# 3. GROUPING NUMBERS
# ============================================================

print("\n3. GROUPING NUMBERS")

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Group by even/odd
groups = groupby(numbers, key=lambda x: x % 2 == 0)
for is_even, group in groups:
    label = "Even" if is_even else "Odd"
    print(f"      {label}: {list(group)}")


# ============================================================
# 4. GROUPING DICTIONARIES
# ============================================================

print("\n4. GROUPING DICTIONARIES")

students = [
    {"name": "Alice", "grade": "A"},
    {"name": "Bob", "grade": "B"},
    {"name": "Charlie", "grade": "A"},
    {"name": "Diana", "grade": "C"},
    {"name": "Eve", "grade": "B"}
]

# Sort by grade first
sorted_students = sorted(students, key=lambda x: x["grade"])
groups = groupby(sorted_students, key=lambda x: x["grade"])

print("   Students by grade:")
for grade, group in groups:
    names = [s["name"] for s in group]
    print(f"      Grade {grade}: {names}")


# ============================================================
# 5. IMPORTANT: groupby requires sorted data
# ============================================================

print("\n5. IMPORTANT: groupby requires sorted data")

# Wrong - not sorted
unsorted = ["apple", "banana", "apple", "banana", "apple"]
print(f"   Unsorted data: {unsorted}")
groups = groupby(unsorted)
for key, group in groups:
    print(f"      {key}: {list(group)}")

# Notice 'apple' appears twice because data isn't sorted

print("\n   ✅ Always sort before using groupby!")

groupby key points:

  • Groups consecutive items — based on a key function
  • Must be sorted — data must be sorted by the key
  • Returns (key, group) — key is the grouping value
  • Group is an iterator — consume it once

Quick Check: What must you do before using groupby? (Answer: Sort your data by the grouping key)

Real-World Example

5

Building a Data Analysis Pipeline

# Real-World Example: Data Analysis Pipeline

from itertools import (
    chain, islice, groupby, 
    combinations, permutations,
    product, zip_longest,
    takewhile, dropwhile
)
import random
from datetime import datetime

print("=" * 60)
print("DATA ANALYSIS PIPELINE")
print("=" * 60)

# ============================================================
# GENERATE SAMPLE DATA
# ============================================================

def generate_sales_data(n=30):
    """Generate sample sales data"""
    products = ["Laptop", "Phone", "Tablet", "Monitor", "Keyboard"]
    regions = ["North", "South", "East", "West"]
    months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
    
    data = []
    for i in range(n):
        product = random.choice(products)
        region = random.choice(regions)
        month = random.choice(months)
        sales = random.randint(10, 100)
        data.append({
            "product": product,
            "region": region,
            "month": month,
            "sales": sales
        })
    return data

sales_data = generate_sales_data(30)
print("\n1. GENERATED DATA")
print(f"   {len(sales_data)} records")

# ============================================================
# 1. GROUPBY - Sales by Region
# ============================================================

print("\n2. SALES BY REGION (groupby)")

# Sort by region
sorted_by_region = sorted(sales_data, key=lambda x: x["region"])
region_groups = groupby(sorted_by_region, key=lambda x: x["region"])

print("   Sales by region:")
for region, group in region_groups:
    total = sum(item["sales"] for item in group)
    print(f"      {region}: ${total:,}")

# ============================================================
# 2. GROUPBY - Sales by Month
# ============================================================

print("\n3. SALES BY MONTH (groupby)")

# Sort by month
sorted_by_month = sorted(sales_data, key=lambda x: x["month"])
month_groups = groupby(sorted_by_month, key=lambda x: x["month"])

print("   Sales by month:")
for month, group in month_groups:
    total = sum(item["sales"] for item in group)
    print(f"      {month}: ${total:,}")

# ============================================================
# 3. COMBINATIONS - Product Pairs
# ============================================================

print("\n4. PRODUCT PAIRS (combinations)")

products = sorted(set(item["product"] for item in sales_data))
pairs = list(combinations(products, 2))

print(f"   All product pairs ({len(pairs)} combinations):")
for p1, p2 in pairs[:5]:
    print(f"      {p1} - {p2}")
print("      ...")

# ============================================================
# 4. CHAIN - Flatten Data
# ============================================================

print("\n5. FLATTEN DATA (chain)")

# Create nested data
nested = [
    [{"region": "North", "sales": 100}],
    [{"region": "South", "sales": 200}, {"region": "East", "sales": 300}],
    [{"region": "West", "sales": 400}]
]

flattened = list(chain(*nested))
print(f"   Nested data: {len(nested)} groups")
print(f"   Flattened: {len(flattened)} records")

# ============================================================
# 5. ISLICE - Top Performers
# ============================================================

print("\n6. TOP PERFORMERS (islice)")

# Sort by sales and get top 5
sorted_sales = sorted(sales_data, key=lambda x: x["sales"], reverse=True)
top_5 = list(islice(sorted_sales, 5))

print("   Top 5 sales:")
for item in top_5:
    print(f"      {item['product']}: ${item['sales']:,} ({item['region']})")

# ============================================================
# 6. ZIP_LONGEST - Compare Regions
# ============================================================

print("\n7. COMPARE REGIONS (zip_longest)")

north_sales = [d["sales"] for d in sales_data if d["region"] == "North"]
south_sales = [d["sales"] for d in sales_data if d["region"] == "South"]

# Compare two regions
comparison = list(zip_longest(north_sales, south_sales, fillvalue=0))
print(f"   North sales: {len(north_sales)} records")
print(f"   South sales: {len(south_sales)} records")
print(f"   Comparison (North, South): {comparison[:5]}...")

print("\n" + "=" * 60)
print("KEY TAKEAWAYS:")
print("=" * 60)
print("""
- groupby: Group sales by region or month
- combinations: Find product pairs
- chain: Flatten nested data
- islice: Get top performers
- zip_longest: Compare different regions
""")

Real-world example key points:

  • groupby — group sales by region and month
  • combinations — find product pairs
  • chain — flatten nested data
  • islice — get top performers
  • zip_longest — compare regions

Quick Check: Which itertools function would you use to get the top 5 items? (Answer: islice after sorting)

Best Practices

6

Using Itertools Effectively

# Best Practices for Itertools

from itertools import islice, chain, groupby

print("=" * 60)
print("BEST PRACTICES FOR ITERTOOLS")
print("=" * 60)

# ============================================================
# 1. USE ISLICE INSTEAD OF SLICING
# ============================================================

print("\n1. USE ISLICE INSTEAD OF SLICING")

# Bad - creates a new list
data = range(1000000)
bad_slice = list(data)[:10]  # Creates a huge list first!

# Good - returns an iterator
good_slice = list(islice(data, 10))
print(f"   islice memory efficient: {good_slice}")

# ============================================================
# 2. SORT BEFORE GROUPBY
# ============================================================

print("\n2. SORT BEFORE GROUPBY")

# Good - sort before grouping
data = [3, 1, 2, 3, 1, 2, 3]
sorted_data = sorted(data)
groups = groupby(sorted_data)
print("   Sorted groupby works correctly:")
for key, group in groups:
    print(f"      {key}: {list(group)}")

# Bad - unsorted
groups = groupby(data)
print("   Unsorted groupby doesn't group properly:")
for key, group in groups:
    print(f"      {key}: {list(group)}")

# ============================================================
# 3. CHAIN FOR FLATTENING
# ============================================================

print("\n3. CHAIN FOR FLATTENING")

# Good - using chain
nested = [[1, 2], [3, 4], [5, 6]]
flattened = list(chain(*nested))
print(f"   chain flattening: {flattened}")

# Good - chain.from_iterable (more efficient)
flattened2 = list(chain.from_iterable(nested))
print(f"   chain.from_iterable: {flattened2}")

# ============================================================
# 4. USE COMBINATIONS FOR PAIRS
# ============================================================

print("\n4. USE COMBINATIONS FOR PAIRS")

# Good - combinations
items = ['A', 'B', 'C', 'D']
pairs = list(combinations(items, 2))
print(f"   combinations pairs: {pairs}")

# Bad - nested loops
pairs_bad = [(a, b) for i, a in enumerate(items) for b in items[i+1:]]
print(f"   nested loops pairs: {pairs_bad}")

# ============================================================
# 5. USE ZIP_LONGEST FOR UNEQUAL LISTS
# ============================================================

print("\n5. USE ZIP_LONGEST FOR UNEQUAL LISTS")

list1 = [1, 2, 3]
list2 = ['a', 'b']
list3 = ['x', 'y', 'z', 'w']

# zip stops at shortest
regular = list(zip(list1, list2, list3))
print(f"   Regular zip: {regular}")

# zip_longest fills missing
longest = list(zip_longest(list1, list2, list3, fillvalue='-'))
print(f"   zip_longest: {longest}")

# ============================================================
# 6. SUMMARY
# ============================================================

print("\n" + "=" * 60)
print("BEST PRACTICES SUMMARY")
print("=" * 60)
print("""
- Use islice for memory-efficient slicing
- Sort before using groupby
- Use chain for flattening
- Use combinations for pairs
- Use zip_longest for unequal lists
- Itertools functions are memory efficient
""")

Best practices summary:

  • Use islice — memory-efficient slicing
  • Sort before groupby — groupby requires sorted data
  • Use chain — flatten nested data
  • Use combinations — for pairs
  • Use zip_longest — for unequal lists

Quick Check: Why should you use islice instead of regular slicing? (Answer: islice is memory-efficient and doesn't create a new list)

Try It Yourself

Experiment with itertools in the editor below.

Loading Pyodide... 0%
Python Code Editor
==================================================
ITERTOOLS - PRACTICE
==================================================

1. INFINITE ITERATORS
count(10,2) first 5: [10, 12, 14, 16, 18]
cycle(['R','G','B']) first 7: ['R', 'G', 'B', 'R', 'G', 'B', 'R']
repeat('Hello', 4): ['Hello', 'Hello', 'Hello', 'Hello']

2. FINITE ITERATORS
chain([1,2], [3,4], [5,6]): [1, 2, 3, 4, 5, 6]
zip_longest([1,2,3], ['a','b']): [(1, 'a'), (2, 'b'), (3, '-')]

3. COMBINATORICS
product(['A', 'B', 'C'], repeat=2): [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')]
permutations(['A', 'B', 'C'], 2): [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]
combinations(['A', 'B', 'C'], 2): [('A', 'B'), ('A', 'C'), ('B', 'C')]

4. GROUPBY
Words by first letter:
a: ['apple', 'apricot']
b: ['banana', 'blueberry']
c: ['cherry', 'coconut']
🏆

You've Got It!

You now understand the itertools module in Python. You know how to use infinite iterators, combinatoric generators, and group data efficiently.

Quick Quiz

Test what you've learned:

1. Which itertools function creates infinite counting?
2. What must you do before using groupby?
3. Which function returns all possible orderings?
4. What does zip_longest do?
5. Which function combines multiple iterables?

Frequently Asked Questions

What is itertools in Python? ▼

itertools is a built-in Python module that provides fast, memory-efficient tools for working with iterators. It includes functions for infinite iterators, combinatoric generators, and advanced iteration patterns.

What's the difference between combinations and permutations? ▼

permutations returns all possible orderings where order matters. combinations returns all possible selections where order doesn't matter. For example, ('A', 'B') and ('B', 'A') are different in permutations but the same in combinations.

Why do I need to sort data before using groupby? ▼

groupby groups consecutive items that have the same key. If your data isn't sorted by the key, items with the same key won't be grouped together because they're not consecutive. Sorting ensures all items with the same key appear together.

Is itertools memory efficient? ▼

Yes! All itertools functions return iterators (generators) that produce values lazily. This means they don't store all values in memory at once, making them very memory efficient for large datasets.

Can I use itertools with regular lists? ▼

Yes, itertools works with any iterable, including lists, tuples, strings, and generators. You can pass them directly to itertools functions and they'll work the same way.

What's the most useful itertools function? ▼

It depends on your need, but chain (combining iterables), product (Cartesian product), and groupby (grouping data) are among the most commonly used and useful functions.

Where to Go From Here

Now that you understand the itertools module, check out these related topics:

Collections Module

Learn about specialized container data types.

Learn More →

Functools Module

Learn about higher-order functions and decorators.

Learn More →

Generators

Learn about generators — the foundation of itertools.

Learn More →
Interview Resources
  • Python Syntax & Variables Interview Questions
  • Top SQL Interview Questions & Answers
  • SQL Joins: Displaying Data from Multiple Tables FAQ
  • Python Lists and Dictionaries Interview Questions
  • Python OOP Interview Questions
  • SQL Set Operators Interview Questions
Previous: Collections Next: Functools →