Dictionaries and Sets in Python
Dictionaries and sets are powerful data structures that solve common programming problems efficiently. Dictionaries store key-value pairs for fast lookups, while sets store unique values and perform set operations. Both are essential tools in every Python programmer's toolkit.
What are Dictionaries?
A dictionary is an unordered collection of key-value pairs. Each key must be unique and maps to a value.
# Creating dictionaries
student = {
'name': 'Alice',
'age': 20,
'grade': 'A',
'gpa': 3.8
}
# Access values by key
print(student['name']) # 'Alice'
print(student['gpa']) # 3.8
# Empty dictionary
empty_dict = {}
empty_dict2 = dict()
Key Characteristics
- Unordered: No guaranteed order (Python 3.7+ maintains insertion order)
- Mutable: Can add, modify, or remove items
- Keys must be immutable: strings, numbers, tuples (not lists)
- Values can be anything: any data type
- Fast lookups: O(1) average time complexity
Creating Dictionaries
# Direct assignment
person = {'name': 'Bob', 'age': 30}
# Using dict() constructor
person = dict(name='Bob', age=30)
# From list of tuples
pairs = [('name', 'Charlie'), ('age', 25)]
person = dict(pairs)
# Dictionary comprehension
squares = {x: x**2 for x in range(6)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# From two lists using zip
keys = ['name', 'age', 'city']
values = ['Diana', 28, 'Paris']
person = dict(zip(keys, values))
Accessing Dictionary Values
student = {'name': 'Alice', 'age': 20, 'grade': 'A'}
# Using square brackets
name = student['name']
# Using get() method (safer - returns None if key doesn't exist)
age = student.get('age')
email = student.get('email') # Returns None
email = student.get('email', 'not provided') # Custom default
# Check if key exists
if 'grade' in student:
print(f"Grade: {student['grade']}")
if 'email' not in student:
print("No email on file")
Modifying Dictionaries
student = {'name': 'Bob', 'age': 20}
# Add new key-value pair
student['email'] = 'bob@email.com'
student['gpa'] = 3.5
# Modify existing value
student['age'] = 21
# Update multiple items
student.update({'grade': 'B', 'major': 'CS'})
# Remove items
del student['email'] # Remove by key
gpa = student.pop('gpa') # Remove and return value
student.popitem() # Remove and return last item
# Clear all items
student.clear()
Dictionary Methods
person = {'name': 'Alice', 'age': 25, 'city': 'NYC'}
# keys(), values(), items()
print(person.keys()) # dict_keys(['name', 'age', 'city'])
print(person.values()) # dict_values(['Alice', 25, 'NYC'])
print(person.items()) # dict_items([('name', 'Alice'), ...])
# Convert to lists
keys_list = list(person.keys())
values_list = list(person.values())
# setdefault(): Get value or set if doesn't exist
email = person.setdefault('email', 'default@email.com')
# copy(): Create shallow copy
person_copy = person.copy()
Looping Through Dictionaries
grades = {'Alice': 85, 'Bob': 92, 'Charlie': 78}
# Loop through keys
for name in grades:
print(name)
# Loop through keys explicitly
for name in grades.keys():
print(name)
# Loop through values
for grade in grades.values():
print(grade)
# Loop through key-value pairs
for name, grade in grades.items():
print(f"{name}: {grade}")
# With enumerate
for index, (name, grade) in enumerate(grades.items()):
print(f"{index}: {name} = {grade}")
Nested Dictionaries
# Dictionary of dictionaries
students = {
'student1': {'name': 'Alice', 'age': 20, 'gpa': 3.8},
'student2': {'name': 'Bob', 'age': 21, 'gpa': 3.5},
'student3': {'name': 'Charlie', 'age': 19, 'gpa': 3.9}
}
# Access nested values
print(students['student1']['name']) # 'Alice'
# Loop through nested dict
for student_id, info in students.items():
print(f"{student_id}:")
for key, value in info.items():
print(f" {key}: {value}")
# Add to nested dictionary
students['student4'] = {'name': 'Diana', 'age': 20, 'gpa': 4.0}
Dictionary Comprehensions
# Create dictionary from expression
squares = {x: x**2 for x in range(6)}
# Filter with condition
even_squares = {x: x**2 for x in range(10) if x % 2 == 0}
# Transform existing dict
temps_celsius = {'morning': 20, 'noon': 25, 'evening': 22}
temps_fahrenheit = {time: (temp * 9/5) + 32
for time, temp in temps_celsius.items()}
# Create dict from two lists
names = ['Alice', 'Bob', 'Charlie']
ages = [20, 21, 19]
students = {name: age for name, age in zip(names, ages)}
What are Sets?
A set is an unordered collection of unique items.
# Creating sets
fruits = {'apple', 'banana', 'cherry'}
numbers = {1, 2, 3, 4, 5}
# Sets automatically remove duplicates
numbers = {1, 2, 2, 3, 3, 3}
print(numbers) # {1, 2, 3}
# Empty set (must use set(), not {})
empty_set = set()
# Create from list
my_list = [1, 2, 2, 3, 3, 3]
unique = set(my_list)
print(unique) # {1, 2, 3}
Key Characteristics
- Unordered: No indexing or order
- Unique: No duplicate values
- Mutable: Can add/remove items
- Items must be immutable: no lists or dicts as elements
- Fast membership testing: O(1) average
Set Operations
# Add and remove
fruits = {'apple', 'banana'}
fruits.add('cherry')
fruits.add('apple') # No effect - already exists
fruits.remove('banana') # Raises error if not found
fruits.discard('orange') # No error if not found
fruits.pop() # Remove arbitrary element
fruits.clear() # Remove all
# Membership testing
if 'apple' in fruits:
print("We have apples")
Mathematical Set Operations
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
# Union (all elements from both)
union = set1 | set2 # or set1.union(set2)
print(union) # {1, 2, 3, 4, 5, 6, 7, 8}
# Intersection (common elements)
intersection = set1 & set2 # or set1.intersection(set2)
print(intersection) # {4, 5}
# Difference (in set1 but not set2)
difference = set1 - set2 # or set1.difference(set2)
print(difference) # {1, 2, 3}
# Symmetric difference (in either but not both)
sym_diff = set1 ^ set2 # or set1.symmetric_difference(set2)
print(sym_diff) # {1, 2, 3, 6, 7, 8}
# Subset and superset
set_a = {1, 2, 3}
set_b = {1, 2, 3, 4, 5}
print(set_a.issubset(set_b)) # True
print(set_b.issuperset(set_a)) # True
print(set_a.isdisjoint(set_b)) # False (have common elements)
Practical Examples
Example 1: Word Frequency Counter
text = "the quick brown fox jumps over the lazy dog the fox"
words = text.split()
# Count word frequencies
word_count = {}
for word in words:
word_count[word] = word_count.get(word, 0) + 1
print("Word frequencies:")
for word, count in word_count.items():
print(f"{word}: {count}")
# Using Counter from collections
from collections import Counter
word_count = Counter(words)
print(word_count.most_common(3)) # Top 3 words
Example 2: Student Grade Book
# Store student grades
gradebook = {
'Alice': [85, 92, 78, 90],
'Bob': [75, 88, 82, 86],
'Charlie': [95, 89, 93, 91]
}
# Calculate averages
print("Student Averages:")
for student, grades in gradebook.items():
average = sum(grades) / len(grades)
print(f"{student}: {average:.1f}")
# Add new grade
gradebook['Alice'].append(88)
# Find top student
best_student = max(gradebook.items(),
key=lambda x: sum(x[1])/len(x[1]))
print(f"\nTop student: {best_student[0]}")
Example 3: Remove Duplicates While Preserving Order
# Using dict (Python 3.7+)
def remove_duplicates(items):
return list(dict.fromkeys(items))
numbers = [1, 2, 3, 2, 4, 3, 5, 1]
unique = remove_duplicates(numbers)
print(unique) # [1, 2, 3, 4, 5]
Example 4: Find Common and Unique Elements
# Students in two classes
class_a = {'Alice', 'Bob', 'Charlie', 'Diana'}
class_b = {'Charlie', 'Diana', 'Eve', 'Frank'}
# Students in both classes
both = class_a & class_b
print(f"In both classes: {both}")
# Students in only one class
only_a = class_a - class_b
only_b = class_b - class_a
print(f"Only in A: {only_a}")
print(f"Only in B: {only_b}")
# All students
all_students = class_a | class_b
print(f"All students: {all_students}")
Example 5: Configuration Management
# Default settings
defaults = {
'theme': 'light',
'language': 'en',
'notifications': True,
'auto_save': True
}
# User preferences
user_prefs = {
'theme': 'dark',
'notifications': False
}
# Merge settings (user prefs override defaults)
settings = {**defaults, **user_prefs}
print("Final settings:", settings)
Common Patterns
Pattern 1: Group Items by Property
# Group students by grade
students = [
{'name': 'Alice', 'grade': 'A'},
{'name': 'Bob', 'grade': 'B'},
{'name': 'Charlie', 'grade': 'A'},
{'name': 'Diana', 'grade': 'C'},
{'name': 'Eve', 'grade': 'B'}
]
by_grade = {}
for student in students:
grade = student['grade']
if grade not in by_grade:
by_grade[grade] = []
by_grade[grade].append(student['name'])
print(by_grade)
# {'A': ['Alice', 'Charlie'], 'B': ['Bob', 'Eve'], 'C': ['Diana']}
Pattern 2: Count Occurrences
items = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple']
counts = {}
for item in items:
counts[item] = counts.get(item, 0) + 1
print(counts) # {'apple': 3, 'banana': 2, 'cherry': 1}
Pattern 3: Invert Dictionary
# Swap keys and values
original = {'a': 1, 'b': 2, 'c': 3}
inverted = {value: key for key, value in original.items()}
print(inverted) # {1: 'a', 2: 'b', 3: 'c'}
Practice Exercises
Exercise 1: Phone Book
Create a phone book application with:
- Add contact
- Search contact
- Update contact
- Delete contact
- List all contacts
Exercise 2: Inventory System
Build an inventory manager:
- Add product (name, quantity, price)
- Update quantity
- Calculate total inventory value
- Find low stock items
Exercise 3: Unique Visitor Counter
Track website visitors:
- Add visitor ID
- Count unique visitors
- Find common visitors across days
Sample Solutions
Exercise 1:
phone_book = {}
def add_contact(name, number):
phone_book[name] = number
def search_contact(name):
return phone_book.get(name, "Not found")
def update_contact(name, number):
if name in phone_book:
phone_book[name] = number
return True
return False
def delete_contact(name):
if name in phone_book:
del phone_book[name]
return True
return False
def list_contacts():
for name, number in sorted(phone_book.items()):
print(f"{name}: {number}")
# Usage
add_contact("Alice", "555-0001")
add_contact("Bob", "555-0002")
list_contacts()
Key Takeaways
Dictionaries:
- Store key-value pairs
- Fast lookups by key
- Keys must be immutable
- Use for mappings and associations
Sets:
- Store unique values only
- Fast membership testing
- Support mathematical operations
- Use for removing duplicates and set operations
When to Use Which:
- Dictionary: Store related data (person info, config settings)
- Set: Track unique items, membership testing, set operations
What's Next?
- Loops - Iterate through dictionaries and sets
- Functions - Process these data structures
- Classes and Objects - Combine data and behavior
Dictionaries and sets are powerful tools for organizing data. Master them to write more efficient and Pythonic code!
