Python • Key-Value Data

Python Dictionaries Deep Dive

Master dictionaries – from creation and methods to comprehension, nested structures, and advanced topics. Then build a real‑world student grade manager that ties everything together.

📖

Key‑Value Mapping

Keys must be immutable (str, int, tuple) and unique.

O(1) Lookups

Implemented with hash tables – ultra‑fast get/set.

🧩

Mutable & Flexible

Add, remove, or change key‑value pairs anytime.

📚

Collections Module

defaultdict, Counter – built‑in power tools.

1. Creating a Dictionary

You can create a dictionary with curly braces {} or the dict() constructor. Keys must be immutable (strings, numbers, tuples) while values can be any object.

create_dict.py
# Empty dictionary
student = {}

# With initial values
student = {
    "name": "Aarav",
    "grade": 8,
    "subjects": ["Maths", "Science", "English"]
}

# Using dict() constructor
grades = dict(maths=95, science=88, english=92)

# Using fromkeys() – all keys get same value
names = ["Alice", "Bob", "Charlie"]
default_dict = dict.fromkeys(names, 0)
print(default_dict)   # {'Alice': 0, 'Bob': 0, 'Charlie': 0}

print(student)
print(grades)
✨ Pro Tip: Use dict.fromkeys() when you need a dictionary with the same default value for all keys (e.g., counters).

2. Accessing Values

Use square brackets [] (raises KeyError if missing) or the safer .get() method.

access_dict.py
student = {"name": "Aarav", "grade": 8, "marks": 84.5}

# Direct access (raises KeyError if key missing)
print(student["name"])       # Aarav

# Safe access with .get()
print(student.get("age"))    # None
print(student.get("age", 15)) # 15 (default value)

# Set default if missing (modifies dictionary)
student.setdefault("city", "Jaipur")
print(student)
Aarav None 15 {'name': 'Aarav', 'grade': 8, 'marks': 84.5, 'city': 'Jaipur'}
⚠️ KeyError: Accessing a missing key with student["age"] crashes the program. Always use .get() when the key might not exist.

3. Adding and Updating Items

Assign a value to a new key to add it; assign to an existing key to update.

update_dict.py
student = {"name": "Aarav", "grade": 8}

# Add new key
student["school"] = "XYZ Public School"

# Update existing key
student["grade"] = 9

# Bulk update using .update()
student.update({"marks": 88.5, "city": "Jaipur"})

print(student)
{'name': 'Aarav', 'grade': 9, 'school': 'XYZ Public School', 'marks': 88.5, 'city': 'Jaipur'}

4. Removing Items

Several ways to delete key‑value pairs.

remove_dict.py
student = {"name": "Aarav", "grade": 8, "city": "Jaipur"}

# Delete specific key with del
del student["city"]

# Remove and return a key with .pop()
grade = student.pop("grade")   # returns 8

# Remove last inserted item (Python 3.7+)
last_item = student.popitem()  # returns ('name', 'Aarav')

# Clear everything
student.clear()

print(grade, last_item, student)
8 ('name', 'Aarav') {}

5. Essential Dictionary Methods

Common methods that return dynamic views or perform actions:

MethodDescription
keys()Returns a view of all keys
values()Returns a view of all values
items()Returns a view of (key, value) tuples
get(key, default)Returns value or default if key missing
update(other_dict)Merges another dictionary into the current one
pop(key, default)Removes key and returns its value
popitem()Removes and returns the last inserted pair
setdefault(key, default)Returns value if key exists; else sets it to default
dict_methods.py
marks = {"maths": 95, "science": 88}

# Looping through items
for subject, score in marks.items():
    print(f"{subject}: {score}")

# Getting all keys
print(list(marks.keys()))     # ['maths', 'science']

# .setdefault example
marks.setdefault("english", 90)  # adds because missing
marks.setdefault("maths", 0)     # does nothing (key exists)
print(marks)
maths: 95 science: 88 ['maths', 'science'] {'maths': 95, 'science': 88, 'english': 90}

6. Looping Through Dictionaries

Use .keys(), .values(), or .items() for clarity and performance.

loop_dict.py
student = {"name": "Aarav", "grade": 8, "marks": 84.5}

# Loop through keys
for key in student:
    print(key, "→", student[key])

# Loop through values
for val in student.values():
    print(val)

# Loop through key‑value pairs (recommended)
for key, val in student.items():
    print(f"{key}: {val}")

7. Nested Dictionaries

Dictionaries can contain other dictionaries – perfect for complex, hierarchical data.

nested_dict.py
class_8 = {
    "Aarav": {"maths": 95, "science": 88},
    "Priya": {"maths": 91, "science": 93}
}

# Access nested value
aarav_science = class_8["Aarav"]["science"]   # 88

# Add new student
class_8["Rohan"] = {"maths": 76, "science": 82}

# Loop through nested dictionary
for name, marks in class_8.items():
    avg = sum(marks.values()) / len(marks)
    print(f"{name}: Avg = {avg:.1f}")
Aarav: Avg = 91.5 Priya: Avg = 92.0 Rohan: Avg = 79.0

8. Dictionary Comprehension

A concise, Pythonic way to create or transform dictionaries in a single line. Syntax: {key_expression: value_expression for item in iterable if condition}.

dict_comp.py
# Square numbers
squares = {x: x**2 for x in range(1, 6)}   # {1:1, 2:4, 3:9, 4:16, 5:25}

# Convert list to dict
words = ["apple", "banana", "cherry"]
word_len = {w: len(w) for w in words}

# Filter with comprehension
marks = {"maths": 95, "science": 88, "history": 72}
high_scores = {k: v for k, v in marks.items() if v >= 80}

# Ternary condition (if‑else inside value)
status = {num: "even" if num % 2 == 0 else "odd" for num in range(1, 6)}

print(squares)
print(word_len)
print(high_scores)
print(status)
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25} {'apple': 5, 'banana': 6, 'cherry': 6} {'maths': 95, 'science': 88} {1: 'odd', 2: 'even', 3: 'odd', 4: 'even', 5: 'odd'}
💡 Performance & Readability: Dictionary comprehensions are often faster and more readable than manual for‑loops. Use them when the logic is simple; for complex transformations, stick with explicit loops.

9. Advanced Dictionary Topics

Beyond the basics: defaultdict, Counter, merging, and frequency counting.

9.1 defaultdict – Auto‑Default for Missing Keys

defaultdict_example.py
from collections import defaultdict

# Group words by their first letter
words = ["apple", "ant", "banana", "ball", "cherry"]
grouped = defaultdict(list)

for word in words:
    grouped[word[0]].append(word)

print(dict(grouped))   # {'a': ['apple', 'ant'], 'b': ['banana', 'ball'], 'c': ['cherry']}

9.2 Counter – Counting Hashable Objects

counter_example.py
from collections import Counter

# Count word frequencies
text = "apple banana apple orange banana apple"
word_counts = Counter(text.split())
print(word_counts)        # Counter({'apple': 3, 'banana': 2, 'orange': 1})
print(word_counts["apple"])  # 3

9.3 Merging Dictionaries (Python 3.9+)

merge_dicts.py
dict1 = {"a": 1, "b": 2}
dict2 = {"b": 3, "c": 4}

# Using | operator (Python 3.9+)
merged = dict1 | dict2    # {'a':1, 'b':3, 'c':4}

# Using ** unpacking (all versions)
merged_v2 = {**dict1, **dict2}

print(merged)
print(merged_v2)

🎯 Mini Project: Student Grade Manager

This project uses dictionaries, lists, tuples, sets, loops, conditionals, input validation and type casting – everything you’ve learned so far. You’ll build a complete program to manage students, store their marks, calculate averages, find toppers, and ensure data integrity.

student_grade_manager.py
"""
Student Grade Manager – Complete Mini Project
Concepts used: dictionaries, lists, tuples, sets, loops, conditionals,
input validation, type casting, f‑strings, and functions.
"""

def main():
    students = []          # list to store dictionaries
    roll_numbers = set()   # set to guarantee unique roll numbers
    
    while True:
        print("\n📚 STUDENT GRADE MANAGER 📚")
        print("1. Add new student")
        print("2. View all students & averages")
        print("3. Find class topper")
        print("4. Students above class average")
        print("5. Check duplicate roll numbers")
        print("6. Exit")
        choice = input("Choose option (1-6): ").strip()
        
        if choice == "1":
            # Input student details
            name = input("Enter student name: ").strip()
            try:
                roll = int(input("Enter roll number: "))
                if roll in roll_numbers:
                    print("⚠️ Roll number already exists! Duplicate not allowed.")
                    continue
            except ValueError:
                print("Roll number must be an integer.")
                continue
            
            # Grade (int)
            try:
                grade = int(input("Enter grade (1-12): "))
                if grade < 1 or grade > 12:
                    print("Invalid grade. Must be 1-12.")
                    continue
            except ValueError:
                print("Invalid input. Grade must be an integer.")
                continue
            
            # Marks for 3 subjects
            marks = []
            subjects = ["Math", "Science", "English"]
            for sub in subjects:
                while True:
                    try:
                        mark = float(input(f"Enter marks for {sub} (0-100): "))
                        if 0 <= mark <= 100:
                            marks.append(mark)
                            break
                        else:
                            print("Marks must be between 0 and 100.")
                    except ValueError:
                        print("Please enter a valid number.")
            
            # Store student as a dictionary
            student = {
                "name": name,
                "roll": roll,
                "grade": grade,
                "marks": tuple(marks),  # immutable tuple for subject marks
                "total": sum(marks),
                "average": sum(marks) / len(marks)
            }
            students.append(student)
            roll_numbers.add(roll)
            print(f"✅ Student {name} (Roll {roll}) added successfully!")
        
        elif choice == "2":
            if not students:
                print("No students yet.")
                continue
            # Display all students
            print("\n📊 ALL STUDENTS REPORT 📊")
            print(f"{'Name':<12} {'Roll':<6} {'Grade':<6} {'Marks':<25} {'Total':<6} {'Average':<8}")
            print("-" * 75)
            for s in students:
                marks_str = ", ".join(str(m) for m in s["marks"])
                print(f"{s['name']:<12} {s['roll']:<6} {s['grade']:<6} {marks_str:<25} {s['total']:<6} {s['average']:<8.2f}")
        
        elif choice == "3":
            if not students:
                print("No students yet.")
                continue
            # Find topper (maximum total)
            topper = max(students, key=lambda x: x["total"])
            print(f"🏆 Topper: {topper['name']} (Roll {topper['roll']}) with total {topper['total']} and average {topper['average']:.2f}")
        
        elif choice == "4":
            if not students:
                print("No students yet.")
                continue
            # Calculate class average
            class_avg = sum(s["average"] for s in students) / len(students)
            print(f"\n📈 Class Average: {class_avg:.2f}")
            print("Students scoring above class average:")
            for s in students:
                if s["average"] > class_avg:
                    print(f"  - {s['name']} (Roll {s['roll']}): {s['average']:.2f}")
        
        elif choice == "5":
            # Check uniqueness of roll numbers using set
            if len(roll_numbers) == len(students):
                print("✅ All roll numbers are unique.")
            else:
                print("⚠️ Duplicate roll numbers found! (Should not happen with our validation)")
            print(f"Total unique roll numbers: {len(roll_numbers)}")
            print(f"Roll numbers: {sorted(roll_numbers)}")
        
        elif choice == "6":
            print("Goodbye! Keep coding 🐍")
            break
        else:
            print("Invalid option. Please try again.")

if __name__ == "__main__":
    main()
💡 Project Highlights:
Dictionaries store each student record with named fields.
Tuples keep subject marks immutable.
Sets ensure unique roll numbers.
Loops & conditionals validate input and compute results.
Type casting converts user input to numbers.
List comprehension calculates class average.
Functions structure the code.

Try extending the project: add subject‑wise toppers, sort students by average, save/load data to a file, or generate a grade letter (A/B/C) based on average.

Practice Problems (Solved)

🔰 Beginner Level

1. Word Frequency Counter
sentence = "hello world hello python world python python"
words = sentence.split()
freq = {}
for word in words:
    freq[word] = freq.get(word, 0) + 1
print(freq)   # {'hello': 2, 'world': 2, 'python': 3}
2. Student Grade Aggregator
students = {
    "Aarav": {"maths": 95, "science": 88},
    "Priya": {"maths": 91, "science": 93}
}
top_student = None
highest_avg = 0
for name, marks in students.items():
    avg = sum(marks.values()) / len(marks)
    if avg > highest_avg:
        highest_avg = avg
        top_student = name
print(f"{top_student} has the highest average: {highest_avg:.1f}")

⚡ Intermediate Level

3. Invert a Dictionary
original = {"a": 1, "b": 2, "c": 1}
inverted = {}
for k, v in original.items():
    inverted.setdefault(v, []).append(k)
print(inverted)   # {1: ['a', 'c'], 2: ['b']}
4. Group Anagrams
from collections import defaultdict
words = ["eat", "tea", "tan", "ate", "nat", "bat"]
anagrams = defaultdict(list)
for word in words:
    key = ''.join(sorted(word))
    anagrams[key].append(word)
print(list(anagrams.values()))

Unsolved Exercises

Challenge yourself – no solutions here, but you can use the solved examples and the mini project as inspiration.

🔰 Beginner Level

1. Phone Book Lookup

Create a dictionary with names and phone numbers. Ask the user for a name and print the number (or "Not found").

Write your code here – solution not shown.
2. Merge Two Dictionaries

Combine dict1 and dict2 – values from dict2 overwrite dict1 if keys conflict.

Write your code here – solution not shown.

⚡ Intermediate Level

3. Count Character Frequencies (case‑insensitive)
Write your code here – solution not shown.
4. Find the First Non‑Repeating Character in a String
Write your code here – solution not shown.

🔥 Advanced (DSA / Interview)

5. Two Sum

Given an array of integers nums and a target integer, find the indices of the two numbers that add up to target. Use a dictionary for O(n) time.

Write your code here – solution not shown.

Test case: nums = [2,7,11,15], target = 9[0,1]

6. Longest Substring Without Repeating Characters

Given a string, find the length of the longest substring without repeating characters. Use a dictionary to track the latest index of each character.

Write your code here – solution not shown.
7. Group Anagrams from a List of Strings

Group words that are anagrams. Use defaultdict(list) with sorted word as key.

Write your code here – solution not shown.