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: Collections Module

Python Collections Module - Complete Guide

Specialized data structures that make your code more efficient.

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 Collections Module?
  • Counter - Counting Items
  • defaultdict - Auto Defaults
  • OrderedDict - Remember Order
  • deque - Fast Appends & Pops
  • namedtuple - Lightweight Objects
  • 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 collections module — specialized container data types
  • Counter — count items in a sequence
  • defaultdict — dictionary with default values
  • OrderedDict — dictionary that remembers order
  • deque — fast operations from both ends
  • namedtuple — lightweight immutable objects

What is Collections Module?

The collections module is a built-in Python module that provides specialized container data types that are more powerful than the basic ones like lists, tuples, and dictionaries.

Think of the collections module like a toolbox with specialized tools. A regular list or dictionary is like a hammer – it works for many jobs. But sometimes you need a specialized tool like a screwdriver or a wrench – that's what collections gives you.

💡 Key concept: Collections module gives you specialized data structures that make your code more efficient and easier to write.

Counter - Counting Items

1

Count How Many Times Each Item Appears

Counter is a dictionary subclass that counts how many times each item appears in a sequence. It's perfect for counting words, characters, or any items.

# Counter - Counting Items

from collections import Counter

print("=" * 50)
print("COUNTER - COUNTING ITEMS")
print("=" * 50)

# ============================================================
# BASIC COUNTER
# ============================================================

print("\n1. BASIC COUNTER")

# Count items in a list
colors = ["red", "blue", "red", "green", "blue", "red", "yellow"]
color_counts = Counter(colors)
print(f"   Colors: {colors}")
print(f"   Counts: {color_counts}")

# Access counts like a dictionary
print(f"   Red count: {color_counts['red']}")
print(f"   Blue count: {color_counts['blue']}")
print(f"   Green count: {color_counts['green']}")


# ============================================================
# COUNTING WORDS IN A STRING
# ============================================================

print("\n2. COUNTING WORDS IN A STRING")

text = "the cat in the hat the cat sat on the mat"
words = text.split()
word_counts = Counter(words)
print(f"   Text: {text}")
print(f"   Word counts: {word_counts}")


# ============================================================
# MOST COMMON ITEMS
# ============================================================

print("\n3. MOST COMMON ITEMS")

# Get the most common items
print(f"   Top 2 most common: {word_counts.most_common(2)}")
print(f"   Top 3 most common: {word_counts.most_common(3)}")

# All items sorted by count
print(f"   All sorted: {word_counts.most_common()}")


# ============================================================
# COUNTER METHODS
# ============================================================

print("\n4. COUNTER METHODS")

counter1 = Counter(a=3, b=2, c=1)
counter2 = Counter(a=1, b=2, c=3, d=1)

print(f"   Counter 1: {counter1}")
print(f"   Counter 2: {counter2}")

# Add two counters
print(f"   Counter 1 + Counter 2: {counter1 + counter2}")

# Subtract counters
print(f"   Counter 1 - Counter 2: {counter1 - counter2}")

# Intersection (min values)
print(f"   Counter 1 & Counter 2: {counter1 & counter2}")

# Union (max values)
print(f"   Counter 1 | Counter 2: {counter1 | counter2}")

# Total count
print(f"   Total items in counter1: {sum(counter1.values())}")


# ============================================================
# UPDATING A COUNTER
# ============================================================

print("\n5. UPDATING A COUNTER")

counter = Counter()
print(f"   Empty counter: {counter}")

# Add items
counter.update(["a", "b", "a", "c", "a"])
print(f"   After update: {counter}")

# Add more items
counter.update(["b", "b", "d"])
print(f"   After second update: {counter}")

# Add a dictionary
counter.update({"a": 2, "e": 1})
print(f"   After dict update: {counter}")


# ============================================================
# REMOVING ITEMS
# ============================================================

print("\n6. REMOVING ITEMS")

counter = Counter(a=5, b=3, c=1, d=0)
print(f"   Before: {counter}")

# Remove items with count <= 0
counter += Counter()
print(f"   After removing zeros: {counter}")

# Delete a specific item
del counter['a']
print(f"   After deleting 'a': {counter}")

Counter key points:

  • Counts items — how many times each appears
  • most_common() — returns items sorted by count
  • Update — add more items to count
  • Math operations — add, subtract, intersect, union
  • Dictionary-like — works like a dictionary

Quick Check: How do you get the most common items from a Counter? (Answer: Use counter.most_common(n))

defaultdict - Auto Defaults

2

Dictionary with Automatic Default Values

defaultdict is like a regular dictionary, but it automatically provides a default value for keys that don't exist. No more KeyError!

# defaultdict - Auto Defaults

from collections import defaultdict

print("=" * 50)
print("DEFAULTDICT - AUTO DEFAULTS")
print("=" * 50)

# ============================================================
# BASIC DEFAULTDICT
# ============================================================

print("\n1. BASIC DEFAULTDICT")

# Regular dictionary - KeyError if key doesn't exist
regular = {}
try:
    print(regular['missing'])
except KeyError:
    print("   Regular dict: KeyError!")

# defaultdict - returns default value
dd = defaultdict(int)  # int() returns 0
print(f"   dd['missing']: {dd['missing']}")  # Returns 0
print(f"   dd: {dd}")  # Key was created!


# ============================================================
# DIFFERENT DEFAULT TYPES
# ============================================================

print("\n2. DIFFERENT DEFAULT TYPES")

# Default: list (empty list)
dd_list = defaultdict(list)
dd_list['fruits'].append('apple')
dd_list['fruits'].append('banana')
print(f"   Default list: {dd_list}")

# Default: int (0)
dd_int = defaultdict(int)
dd_int['count'] += 1
dd_int['count'] += 1
print(f"   Default int: {dd_int}")

# Default: str (empty string)
dd_str = defaultdict(str)
dd_str['name'] += 'Alice'
print(f"   Default str: {dd_str}")

# Default: set (empty set)
dd_set = defaultdict(set)
dd_set['tags'].add('python')
dd_set['tags'].add('programming')
print(f"   Default set: {dd_set}")


# ============================================================
# CUSTOM DEFAULT
# ============================================================

print("\n3. CUSTOM DEFAULT")

# Your own default function
def default_value():
    return "Not Found"

dd_custom = defaultdict(default_value)
print(f"   dd_custom['missing']: {dd_custom['missing']}")
print(f"   dd_custom: {dd_custom}")


# ============================================================
# GROUPING ITEMS WITH DEFAULTDICT
# ============================================================

print("\n4. GROUPING ITEMS")

fruits = [
    ("apple", 5), ("banana", 3), ("apple", 2),
    ("orange", 4), ("banana", 1), ("apple", 3)
]

# Group by fruit name
grouped = defaultdict(list)
for fruit, count in fruits:
    grouped[fruit].append(count)

print(f"   Fruits: {fruits}")
print(f"   Grouped: {grouped}")

# Sum counts by fruit
total_counts = defaultdict(int)
for fruit, count in fruits:
    total_counts[fruit] += count

print(f"   Total counts: {total_counts}")


# ============================================================
# DEFAULTDICT VS REGULAR DICT
# ============================================================

print("\n5. DEFAULTDICT VS REGULAR DICT")

# Without defaultdict (more code)
groups = {}
for fruit, count in fruits:
    if fruit not in groups:
        groups[fruit] = []
    groups[fruit].append(count)
print(f"   Regular dict way: {groups}")

# With defaultdict (less code)
groups_dd = defaultdict(list)
for fruit, count in fruits:
    groups_dd[fruit].append(count)
print(f"   defaultdict way: {groups_dd}")

print("   defaultdict saves you from checking if keys exist!")

defaultdict key points:

  • Auto default — no more KeyError
  • Default types — int, list, set, str, custom
  • Grouping — perfect for grouping items
  • Less code — no need to check if key exists
  • Default factory — function that creates default values

Quick Check: What happens when you access a missing key in a defaultdict? (Answer: It creates the key with a default value)

OrderedDict - Remember Order

3

Dictionary That Remembers Insertion Order

OrderedDict is a dictionary that remembers the order in which items were added. In Python 3.7+, regular dictionaries also remember order, but OrderedDict has additional methods.

# OrderedDict - Remember Order

from collections import OrderedDict

print("=" * 50)
print("ORDEREDDICT - REMEMBER ORDER")
print("=" * 50)

# ============================================================
# BASIC ORDEREDDICT
# ============================================================

print("\n1. BASIC ORDEREDDICT")

# Regular dict (Python 3.7+ also remembers order)
regular = {}
regular['first'] = 1
regular['second'] = 2
regular['third'] = 3
print(f"   Regular dict: {regular}")

# OrderedDict
ordered = OrderedDict()
ordered['first'] = 1
ordered['second'] = 2
ordered['third'] = 3
print(f"   OrderedDict: {ordered}")


# ============================================================
# MOVING ITEMS
# ============================================================

print("\n2. MOVING ITEMS")

ordered = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
print(f"   Original: {ordered}")

# Move to end
ordered.move_to_end('b')
print(f"   Move 'b' to end: {ordered}")

# Move to beginning
ordered.move_to_end('b', last=False)
print(f"   Move 'b' to start: {ordered}")


# ============================================================
# POPPING ITEMS
# ============================================================

print("\n3. POPPING ITEMS")

ordered = OrderedDict([('a', 1), ('b', 2), ('c', 3)])

# Pop from the end (LIFO)
last = ordered.popitem()
print(f"   Popped last: {last}")
print(f"   Remaining: {ordered}")

# Pop from the beginning (FIFO)
first = ordered.popitem(last=False)
print(f"   Popped first: {first}")
print(f"   Remaining: {ordered}")


# ============================================================
# REVERSING ORDER
# ============================================================

print("\n4. REVERSING ORDER")

ordered = OrderedDict([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
print(f"   Original: {ordered}")

reversed_od = OrderedDict(reversed(ordered.items()))
print(f"   Reversed: {reversed_od}")


# ============================================================
# ORDEREDDICT VS REGULAR DICT
# ============================================================

print("\n5. ORDEREDDICT VS REGULAR DICT")

# Equality check with regular dict
od1 = OrderedDict([('a', 1), ('b', 2)])
od2 = OrderedDict([('b', 2), ('a', 1)])

print(f"   OrderedDict 1: {od1}")
print(f"   OrderedDict 2: {od2}")
print(f"   od1 == od2: {od1 == od2}")  # False - order matters!

# Regular dicts are equal regardless of order
d1 = {'a': 1, 'b': 2}
d2 = {'b': 2, 'a': 1}
print(f"   Regular dict 1: {d1}")
print(f"   Regular dict 2: {d2}")
print(f"   d1 == d2: {d1 == d2}")  # True - order doesn't matter

OrderedDict key points:

  • Remembers order — insertion order is preserved
  • move_to_end() — move items to start or end
  • popitem() — pop from start or end
  • Order matters — equality checks consider order
  • Reversed — can be reversed

Quick Check: How do you move an item to the end in OrderedDict? (Answer: ordered.move_to_end(key))

deque - Fast Appends & Pops

4

Double-Ended Queue - Fast Operations on Both Ends

deque (pronounced "deck") is a double-ended queue. It's like a list but optimized for fast operations at both ends.

# deque - Fast Appends & Pops

from collections import deque

print("=" * 50)
print("DEQUE - FAST APPENDS & POPS")
print("=" * 50)

# ============================================================
# BASIC DEQUE
# ============================================================

print("\n1. BASIC DEQUE")

# Creating a deque
d = deque([1, 2, 3, 4, 5])
print(f"   Deque: {d}")

# Append to right (end)
d.append(6)
print(f"   Append 6: {d}")

# Append to left (start)
d.appendleft(0)
print(f"   Appendleft 0: {d}")

# Pop from right
right = d.pop()
print(f"   Pop right: {right}, deque: {d}")

# Pop from left
left = d.popleft()
print(f"   Pop left: {left}, deque: {d}")


# ============================================================
# EXTENDING A DEQUE
# ============================================================

print("\n2. EXTENDING A DEQUE")

d = deque([1, 2, 3])
print(f"   Original: {d}")

# Extend right
d.extend([4, 5, 6])
print(f"   Extend right [4,5,6]: {d}")

# Extend left
d.extendleft([0, -1, -2])
print(f"   Extend left [0,-1,-2]: {d}")


# ============================================================
# ROTATING A DEQUE
# ============================================================

print("\n3. ROTATING A DEQUE")

d = deque([1, 2, 3, 4, 5])
print(f"   Original: {d}")

# Rotate right (positive steps)
d.rotate(2)
print(f"   Rotate right 2: {d}")

# Rotate left (negative steps)
d.rotate(-3)
print(f"   Rotate left 3: {d}")


# ============================================================
# MAXLEN - LIMIT SIZE
# ============================================================

print("\n4. MAXLEN - LIMIT SIZE")

# Limit to 3 items
d = deque(maxlen=3)
d.append(1)
d.append(2)
d.append(3)
print(f"   Deque (maxlen=3): {d}")

# Adding more removes from the other end
d.append(4)
print(f"   After append 4: {d}")  # 1 is removed

d.appendleft(0)
print(f"   After appendleft 0: {d}")  # 3 is removed


# ============================================================
# DEQUE VS LIST PERFORMANCE
# ============================================================

print("\n5. DEQUE VS LIST PERFORMANCE")

import time

# List - inserting at beginning is slow
lst = list(range(10000))
start = time.time()
lst.insert(0, -1)
print(f"   List insert at beginning: {time.time() - start:.6f}s")

# Deque - inserting at beginning is fast
dq = deque(range(10000))
start = time.time()
dq.appendleft(-1)
print(f"   Deque appendleft: {time.time() - start:.6f}s")

print("   deque is much faster for operations at both ends!")


# ============================================================
# OTHER DEQUE OPERATIONS
# ============================================================

print("\n6. OTHER DEQUE OPERATIONS")

d = deque([1, 2, 3, 4, 5])
print(f"   Deque: {d}")

# Count occurrences
print(f"   Count of 3: {d.count(3)}")

# Remove first occurrence
d.remove(3)
print(f"   Remove 3: {d}")

# Reverse
d.reverse()
print(f"   Reversed: {d}")

# Clear
d.clear()
print(f"   Cleared: {d}")

deque key points:

  • Fast at both ends — O(1) operations
  • appendleft/append — add to start/end
  • popleft/pop — remove from start/end
  • rotate — shift items
  • maxlen — limit size

Quick Check: What is deque optimized for? (Answer: Fast operations at both ends of the sequence)

namedtuple - Lightweight Objects

5

Tuple with Field Names

namedtuple is a tuple subclass that gives you named fields. It's like a lightweight class that doesn't use much memory.

# namedtuple - Lightweight Objects

from collections import namedtuple

print("=" * 50)
print("NAMEDTUPLE - LIGHTWEIGHT OBJECTS")
print("=" * 50)

# ============================================================
# CREATING A NAMEDTUPLE
# ============================================================

print("\n1. CREATING A NAMEDTUPLE")

# Define a namedtuple
Point = namedtuple('Point', ['x', 'y'])

# Create instances
p1 = Point(1, 2)
p2 = Point(x=3, y=4)

print(f"   Point 1: {p1}")
print(f"   Point 2: {p2}")

# Access by index (like tuple)
print(f"   p1[0]: {p1[0]}, p1[1]: {p1[1]}")

# Access by name (like class)
print(f"   p1.x: {p1.x}, p1.y: {p1.y}")


# ============================================================
# MORE FIELDS
# ============================================================

print("\n2. MORE FIELDS")

# Define with more fields
Person = namedtuple('Person', ['name', 'age', 'city', 'email'])

person = Person("Alice", 30, "NYC", "alice@example.com")
print(f"   Person: {person}")
print(f"   Name: {person.name}")
print(f"   Age: {person.age}")
print(f"   City: {person.city}")
print(f"   Email: {person.email}")


# ============================================================
# DEFAULT VALUES
# ============================================================

print("\n3. DEFAULT VALUES")

# With default values (Python 3.7+)
Person = namedtuple('Person', ['name', 'age', 'city'], defaults=['Unknown', 0, 'Unknown'])

p1 = Person("Alice", 30)
p2 = Person("Bob")
p3 = Person("Charlie", 25, "LA")

print(f"   Person 1: {p1}")
print(f"   Person 2: {p2}")
print(f"   Person 3: {p3}")


# ============================================================
# CONVERTING TO DICT AND LIST
# ============================================================

print("\n4. CONVERTING TO DICT AND LIST")

Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)

# Convert to dict
p_dict = p._asdict()
print(f"   As dict: {p_dict}")

# Convert to list
p_list = list(p)
print(f"   As list: {p_list}")

# Convert from dict
p_from_dict = Point(**p_dict)
print(f"   From dict: {p_from_dict}")


# ============================================================
# METHODS AND PROPERTIES
# ============================================================

print("\n5. METHODS AND PROPERTIES")

Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)

# Get all fields
print(f"   Fields: {Point._fields}")

# Create a new instance with a replaced field
p_new = p._replace(x=10)
print(f"   Original: {p}")
print(f"   Replaced x: {p_new}")

# Create from another tuple
p_from_tuple = Point._make([5, 6])
print(f"   From tuple: {p_from_tuple}")


# ============================================================
# NAMEDTUPLE VS CLASS
# ============================================================

print("\n6. NAMEDTUPLE VS CLASS")

# Regular class (more code)
class PointClass:
    def __init__(self, x, y):
        self.x = x
        self.y = y

pc = PointClass(1, 2)
print(f"   Class: PointClass(1, 2)")

# namedtuple (less code)
Point = namedtuple('Point', ['x', 'y'])
pn = Point(1, 2)
print(f"   namedtuple: {pn}")

print("   namedtuple uses less memory and is faster")
print("   namedtuple is immutable (can't change values)")
print("   Class is mutable and can have methods")

namedtuple key points:

  • Named fields — access by name or index
  • Lightweight — uses less memory than classes
  • Immutable — cannot be changed after creation
  • Convertible — to dict, list, and back
  • Default values — can set defaults

Quick Check: What's the advantage of namedtuple over a regular tuple? (Answer: You can access fields by name, not just by index)

Real-World Example

6

Building a Sales Analytics System

# Real-World Example: Sales Analytics System

from collections import Counter, defaultdict, deque, namedtuple, OrderedDict
import random
from datetime import datetime

print("=" * 60)
print("SALES ANALYTICS SYSTEM")
print("=" * 60)

# ============================================================
# DATA TYPES
# ============================================================

# Use namedtuple for sales records
Sale = namedtuple('Sale', ['product', 'category', 'price', 'quantity', 'customer', 'date'])

# Use OrderedDict for monthly reports
MonthlyReport = OrderedDict

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

products = [
    ("Laptop", "Electronics", 999.99),
    ("Phone", "Electronics", 699.99),
    ("Headphones", "Electronics", 149.99),
    ("Book", "Books", 29.99),
    ("Pen", "Stationery", 2.99),
    ("Notebook", "Stationery", 4.99),
    ("Desk", "Furniture", 299.99),
    ("Chair", "Furniture", 199.99)
]

customers = ["Alice", "Bob", "Charlie", "Diana", "Eve", "Frank", "Grace", "Henry"]

def generate_sales(count=50):
    """Generate sample sales data"""
    sales = []
    for i in range(count):
        product, category, price = random.choice(products)
        quantity = random.randint(1, 5)
        customer = random.choice(customers)
        date = datetime(2024, random.randint(1, 12), random.randint(1, 28))
        sales.append(Sale(product, category, price, quantity, customer, date))
    return sales

sales_data = generate_sales(50)
print(f"\n1. Generated {len(sales_data)} sales records")

# ============================================================
# 1. COUNTER - Product Popularity
# ============================================================

print("\n2. PRODUCT POPULARITY (Counter)")

product_counts = Counter(sale.product for sale in sales_data)
print("   Top 5 products:")
for product, count in product_counts.most_common(5):
    print(f"      {product}: {count} sales")

# ============================================================
# 2. DEFAULTDICT - Sales by Category
# ============================================================

print("\n3. SALES BY CATEGORY (defaultdict)")

category_sales = defaultdict(list)
for sale in sales_data:
    category_sales[sale.category].append(sale)

print("   Sales by category:")
for category, sales in category_sales.items():
    total = sum(s.price * s.quantity for s in sales)
    print(f"      {category}: {len(sales)} sales, ${total:.2f} total")

# ============================================================
# 3. DEFAULTDICT - Customer Spending
# ============================================================

print("\n4. CUSTOMER SPENDING (defaultdict)")

customer_spending = defaultdict(float)
for sale in sales_data:
    customer_spending[sale.customer] += sale.price * sale.quantity

print("   Customer spending:")
for customer, total in sorted(customer_spending.items(), key=lambda x: x[1], reverse=True):
    print(f"      {customer}: ${total:.2f}")

# ============================================================
# 4. DEQUE - Recent Sales
# ============================================================

print("\n5. RECENT SALES (deque)")

recent_sales = deque(maxlen=5)
for sale in sales_data[-10:]:  # Last 10 sales
    recent_sales.append(sale)

print("   Most recent 5 sales:")
for sale in recent_sales:
    print(f"      {sale.product} x{sale.quantity} - ${sale.price * sale.quantity:.2f}")

# ============================================================
# 5. ORDEREDDICT - Monthly Report
# ============================================================

print("\n6. MONTHLY REPORT (OrderedDict)")

monthly_report = OrderedDict()
for sale in sales_data:
    month = sale.date.strftime("%Y-%m")
    if month not in monthly_report:
        monthly_report[month] = 0
    monthly_report[month] += sale.price * sale.quantity

print("   Monthly revenue:")
for month, revenue in monthly_report.items():
    print(f"      {month}: ${revenue:.2f}")

# ============================================================
# 6. NAMEDTUPLE - Product Summary
# ============================================================

print("\n7. PRODUCT SUMMARY (namedtuple)")

ProductSummary = namedtuple('ProductSummary', ['name', 'sales_count', 'total_revenue'])

product_summaries = []
for product in set(sale.product for sale in sales_data):
    count = sum(1 for s in sales_data if s.product == product)
    revenue = sum(s.price * s.quantity for s in sales_data if s.product == product)
    product_summaries.append(ProductSummary(product, count, revenue))

print("   Product summaries:")
for summary in sorted(product_summaries, key=lambda x: x.total_revenue, reverse=True)[:5]:
    print(f"      {summary.name}: {summary.sales_count} sales, ${summary.total_revenue:.2f}")

print("\n" + "=" * 60)
print("KEY TAKEAWAYS:")
print("=" * 60)
print("""
- Counter: Count product popularity
- defaultdict: Group by category and customer
- deque: Keep recent sales
- OrderedDict: Track monthly revenue
- namedtuple: Create lightweight data structures
""")

Real-world example key points:

  • Counter — find most popular products
  • defaultdict — group sales by category and customer
  • deque — keep recent sales
  • OrderedDict — track monthly revenue
  • namedtuple — create sale records

Quick Check: Which collection type would you use to keep the last 10 sales? (Answer: deque with maxlen=10)

Best Practices

7

Using Collections Effectively

# Best Practices for Collections

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

from collections import Counter, defaultdict, OrderedDict, deque, namedtuple

# ============================================================
# 1. CHOOSE THE RIGHT TOOL
# ============================================================

print("\n1. CHOOSE THE RIGHT TOOL")

print("""
Use Counter when:
- You need to count occurrences
- You want most common items

Use defaultdict when:
- You need to group items
- You want to avoid KeyError

Use OrderedDict when:
- Order matters for comparisons
- You need to move items

Use deque when:
- You need fast operations at both ends
- You want a queue or stack

Use namedtuple when:
- You want a lightweight object
- You need named fields
""")

# ============================================================
# 2. USE DEFAULTDICT FOR GROUPING
# ============================================================

print("\n2. USE DEFAULTDICT FOR GROUPING")

# Good - clean and concise
data = [('a', 1), ('b', 2), ('a', 3), ('b', 4), ('c', 5)]
grouped = defaultdict(list)
for key, value in data:
    grouped[key].append(value)
print(f"   Grouped: {grouped}")

# Bad - manual checking
grouped_bad = {}
for key, value in data:
    if key not in grouped_bad:
        grouped_bad[key] = []
    grouped_bad[key].append(value)
print(f"   Grouped (manual): {grouped_bad}")

# ============================================================
# 3. USE DEQUE FOR QUEUES
# ============================================================

print("\n3. USE DEQUE FOR QUEUES")

# Good - fast queue operations
queue = deque()
queue.append("first")
queue.append("second")
queue.append("third")
print(f"   Queue: {list(queue)}")
first = queue.popleft()
print(f"   Popped: {first}")
print(f"   Queue after pop: {list(queue)}")

# Bad - using list for queue (slow)
queue_bad = []
queue_bad.append("first")
queue_bad.append("second")
first = queue_bad.pop(0)  # O(n) operation - slow!

# ============================================================
# 4. USE NAMEDTUPLE FOR SIMPLE DATA OBJECTS
# ============================================================

print("\n4. USE NAMEDTUPLE FOR SIMPLE DATA")

# Good - lightweight and clear
Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
print(f"   Point: {p.x}, {p.y}")

# Bad - using tuple (hard to read)
p_tuple = (1, 2)
print(f"   Tuple: {p_tuple[0]}, {p_tuple[1]}")

# ============================================================
# 5. USE COUNTER FOR FREQUENCY ANALYSIS
# ============================================================

print("\n5. USE COUNTER FOR FREQUENCY")

# Good - clean and efficient
words = "the cat in the hat the cat sat on the mat".split()
freq = Counter(words)
print(f"   Frequency: {freq.most_common(2)}")

# Bad - manual counting
freq_bad = {}
for word in words:
    freq_bad[word] = freq_bad.get(word, 0) + 1
print(f"   Manual: {freq_bad}")

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

print("\n" + "=" * 60)
print("BEST PRACTICES SUMMARY")
print("=" * 60)
print("""
- Choose the right collection for your need
- Use defaultdict for grouping
- Use deque for queues and stacks
- Use namedtuple for simple data objects
- Use Counter for counting and frequency
- Use OrderedDict when order matters
""")

Best practices summary:

  • Choose right tool — each has a specific use
  • defaultdict for grouping — cleaner code
  • deque for queues — faster operations
  • namedtuple for data — lightweight objects
  • Counter for frequency — easiest way to count
  • OrderedDict when order matters — explicit ordering

Quick Check: Which collection should you use for a fast queue? (Answer: deque)

Try It Yourself

Experiment with collections in the editor below.

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

1. COUNTER
Numbers: [1, 2, 3, 2, 1, 3, 4, 5, 1, 2, 3, 1]
Counts: Counter({1: 4, 2: 3, 3: 3, 4: 1, 5: 1})
Most common: [(1, 4), (2, 3)]

2. DEFAULTDICT
Groups: defaultdict(, {0: [0, 3, 6, 9], 1: [1, 4, 7], 2: [2, 5, 8]})

3. ORDEREDDICT
OrderedDict: OrderedDict([('a', 1), ('b', 2), ('c', 3)])
Move 'a' to end: OrderedDict([('b', 2), ('c', 3), ('a', 1)])

4. DEQUE
Deque: deque([0, 1, 2, 3, 4])
Pop right: 4
Pop left: 0
After pops: deque([1, 2, 3])

5. NAMEDTUPLE
Student 1: Student(name='Alice', grade=95, subject='Math')
Student 2: Student(name='Bob', grade=87, subject='Science')
Alice got 95 in Math
🏆

You've Got It!

You now understand the collections module in Python. You know how to use Counter, defaultdict, OrderedDict, deque, and namedtuple.

Quick Quiz

Test what you've learned:

1. Which collection is best for counting occurrences?
2. What does defaultdict do?
3. Which collection is best for fast operations at both ends?
4. What is namedtuple?
5. Which collection should you use if order matters for equality?

Frequently Asked Questions

What is the collections module in Python? ▼

The collections module provides specialized container data types like Counter, defaultdict, OrderedDict, deque, and namedtuple. These are more powerful and efficient than basic types for specific use cases.

What's the difference between defaultdict and regular dict? ▼

defaultdict automatically provides a default value when you access a missing key, while a regular dict raises a KeyError. This saves you from having to check if a key exists before accessing it.

Is OrderedDict still needed in Python 3.7+? ▼

Regular dictionaries in Python 3.7+ also remember insertion order. However, OrderedDict has additional methods like move_to_end() and popitem(last=False) that regular dicts don't have. Use OrderedDict when you need these methods.

When should I use deque instead of list? ▼

Use deque when you need fast operations at both ends of the sequence. For example, when implementing a queue or stack. Lists are faster for random access and operations at the end.

What's the advantage of namedtuple over a class? ▼

namedtuple uses less memory and is faster than a regular class. It's immutable and can be accessed by index or by name. It's perfect for simple data objects that don't need methods.

Can I use Counter with custom objects? ▼

Yes, Counter works with any hashable objects. You can count strings, numbers, tuples, and any other hashable type. Custom objects that implement __hash__ can also be counted.

Where to Go From Here

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

Itertools Module

Learn about advanced iteration tools.

Learn More →

Functools Module

Learn about higher-order functions.

Learn More →

Datetime Module

Learn about working with dates and times.

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: Match-Case Next: Itertools →