Master Python Dictionaries

The complete guide to Python's most versatile data structure

What is a Python Dictionary?

Core Characteristics

Key-Value Pairs

Collections of unique keys mapping to values, like a real dictionary

Mutable & Dynamic

Can add, remove, and modify key-value pairs after creation

Insertion Ordered (Python 3.7+)

Maintains the order in which items were added

Basic Dictionary Example

# Creating a student dictionary
student = {
    "name": "Alice Johnson",
    "age": 21,
    "course": "Computer Science",
    "grades": {"math": 95, "python": 98, "algorithms": 92},
    "hobbies": ["coding", "reading", "gaming"],
    "is_active": True
}

# Accessing values
print(student["name"])          # Alice Johnson
print(student.get("age"))       # 21 (safer method)
print(student["grades"]["python"])  # 98 (nested access)

# Dictionary properties
print(type(student))     # 
print(len(student))      # 6 (number of key-value pairs)
print(student.keys())    # dict_keys(['name', 'age', ...])

Key Rules for Dictionary Keys

✅ Allowed Key Types
  • Strings: "name"
  • Integers: 42
  • Floats: 3.14
  • Tuples (if all elements are immutable): (1, 2, 3)
  • Booleans: True, False
❌ Not Allowed as Keys
  • Lists: [1, 2, 3]
  • Dictionaries: {"a": 1}
  • Sets: {1, 2, 3}
  • Any mutable object

Creating Dictionaries - 7 Different Ways

1. Direct Creation

Curly Brace Syntax

student = {"name": "Alice", "age": 21}

dict() Constructor

student = dict(name="Alice", age=21)

2. From Key-Value Pairs

List of Tuples

pairs = [("name", "Alice"), ("age", 21)]
student = dict(pairs)

Two Lists (zip)

keys = ["name", "age", "course"]
values = ["Alice", 21, "CS"]
student = dict(zip(keys, values))

3. Dictionary Comprehension

# Create squares dictionary
squares = {x: x**2 for x in range(1, 6)}
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# With condition
even_squares = {x: x**2 for x in range(10) if x % 2 == 0}
# {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}

4. fromkeys() Method

# All keys get same value
default_dict = dict.fromkeys(["a", "b", "c"], 0)
# {'a': 0, 'b': 0, 'c': 0}

# Without value (defaults to None)
keys = ["name", "age", "email"]
empty_dict = dict.fromkeys(keys)
# {'name': None, 'age': None, 'email': None}

5. Copying Dictionaries

original = {"a": 1, "b": 2}

# Shallow copy (references shared)
copy1 = original.copy()

# Using dict() constructor
copy2 = dict(original)

# Deep copy (for nested dicts)
import copy
deep_copy = copy.deepcopy(original)

Complete Dictionary Methods

Method Description Time Complexity Example & Output
get(key, default) Safe access; returns default if key missing O(1) d.get("name", "Unknown") → "Alice"
setdefault(key, default) Get value if exists, else set to default O(1) d.setdefault("grade", "A") → "A"
pop(key, default) Remove key and return its value O(1) d.pop("age") → 21
popitem() Remove and return last (key, value) pair O(1) d.popitem() → ("course", "CS")
update(other_dict) Merge another dictionary O(n) d.update({"grade": "A"})
clear() Remove all items O(1) d.clear() → {}
keys() Return view of all keys O(1) list(d.keys()) → ["name", "age"]
values() Return view of all values O(1) list(d.values()) → ["Alice", 21]
items() Return view of (key, value) pairs O(1) list(d.items()) → [("name","Alice"),...]

Practical Method Examples

Safe Access Patterns

config = {"theme": "dark", "language": "en"}

# ❌ Risky - raises KeyError
# value = config["font_size"]

# ✅ Safe with get()
value = config.get("font_size", "default")

# ✅ Safe with setdefault (creates if missing)
font = config.setdefault("font_size", 14)

print(config)  # Adds 'font_size': 14 if missing

Iteration Techniques

student = {"name": "Alice", "age": 21, "course": "CS"}

# Loop through keys
for key in student:
    print(key)

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

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

Dictionary Operations & Functions

Common Operations

Membership Testing

student = {"name": "Alice", "age": 21}

# Check key existence
print("name" in student)     # True
print("grade" not in student) # True

# Check value existence
print("Alice" in student.values())  # True

Merging Dictionaries

# Python 3.9+ Merge operator
dict1 = {"a": 1, "b": 2}
dict2 = {"b": 3, "c": 4}

merged = dict1 | dict2  # {'a': 1, 'b': 3, 'c': 4}

# Update in-place
dict1 |= dict2  # dict1 now has dict2's items

Built-in Functions

Utility Functions

inventory = {"apples": 10, "bananas": 5, "oranges": 8}

# Length
print(len(inventory))    # 3

# Sort by keys
sorted_keys = sorted(inventory)  # ['apples', 'bananas', 'oranges']

# Sort by values
sorted_items = sorted(inventory.items(), 
                     key=lambda x: x[1])  
# [('bananas', 5), ('oranges', 8), ('apples', 10)]

# Any/All with dict
print(any(inventory))        # True (non-empty)
print(all(inventory))        # True (all keys truthy)

Dictionary Views

data = {"a": 1, "b": 2, "c": 3}

# Create views (dynamic)
keys_view = data.keys()      # dict_keys(['a', 'b', 'c'])
values_view = data.values()  # dict_values([1, 2, 3])
items_view = data.items()    # dict_items([('a', 1), ...])

# Views update with dictionary
data["d"] = 4
print(list(keys_view))  # ['a', 'b', 'c', 'd']

Advanced Dictionary Concepts

Collections Module Utilities

defaultdict

from collections import defaultdict

# Auto-initialize missing keys
word_counts = defaultdict(int)
for word in ["apple", "banana", "apple"]:
    word_counts[word] += 1
# defaultdict(, {'apple': 2, 'banana': 1})

# With list factory
groups = defaultdict(list)
groups["fruits"].append("apple")  # No KeyError!

OrderedDict

from collections import OrderedDict

# Maintains insertion order (Python <3.7)
ordered = OrderedDict()
ordered["first"] = 1
ordered["second"] = 2
ordered["third"] = 3

# Move to end/beginning
ordered.move_to_end("first")

Counter

from collections import Counter

# Count frequencies
words = ["apple", "banana", "apple", "orange", "banana", "apple"]
counter = Counter(words)
print(counter.most_common(2))  
# [('apple', 3), ('banana', 2)]

Performance & Memory

Hash Table Internals

Dictionaries use hash tables for O(1) average lookup time:

# Hash of key determines storage location hash("name") # Returns integer hash value # Collision resolution via open addressing # Load factor triggers resizing (usually 2/3)

Memory Optimization

# 1. Use __slots__ for many similar objects
class Student:
    __slots__ = ["name", "age"]  # Saves memory
    
# 2. Consider arrays for numeric data
import array
nums = array.array('i', [1, 2, 3])  # More compact

# 3. Use tuples for immutable data
coordinates = (10, 20)  # Less overhead than dict
Performance Tips
  • key in dict is O(1) average case
  • Avoid using mutable objects as keys
  • Prefer dict.get() over try-except for missing keys
  • Use dictionary comprehensions for creation

Real-World Applications

Configuration Management

# App configuration
config = {
    "database": {
        "host": "localhost",
        "port": 5432,
        "user": "admin"
    },
    "server": {
        "port": 8000,
        "debug": True
    },
    "features": ["auth", "logging", "cache"]
}

# Access nested config
db_host = config["database"]["host"]

Data Aggregation

# Sales data aggregation
sales = [
    {"product": "Apple", "amount": 100},
    {"product": "Banana", "amount": 150},
    {"product": "Apple", "amount": 200}
]

# Aggregate by product
totals = {}
for sale in sales:
    product = sale["product"]
    totals[product] = totals.get(product, 0) + sale["amount"]
# {'Apple': 300, 'Banana': 150}

Function Dispatch Table

# Command pattern implementation
def add(x, y):
    return x + y

def multiply(x, y):
    return x * y

def power(x, y):
    return x ** y

# Dispatch table
operations = {
    "add": add,
    "multiply": multiply,
    "power": power
}

# Execute dynamically
result = operations["add"](10, 5)  # 15

Practical Example: Inventory System

Complete Implementation

class InventorySystem:
    def __init__(self):
        self.products = {}
        self.categories = defaultdict(list)
    
    def add_product(self, id, name, price, category):
        self.products[id] = {
            "name": name,
            "price": price,
            "category": category,
            "stock": 0
        }
        self.categories[category].append(id)
    
    def update_stock(self, id, quantity):
        if id in self.products:
            self.products[id]["stock"] += quantity
    
    def get_products_by_category(self, category):
        return {
            pid: self.products[pid] 
            for pid in self.categories.get(category, [])
        }
    
    def __str__(self):
        return f"Inventory with {len(self.products)} products"

# Usage
inventory = InventorySystem()
inventory.add_product("P001", "Laptop", 999.99, "Electronics")
inventory.update_stock("P001", 10)

JSON Serialization

import json

# Dictionary to JSON
data = {
    "name": "Alice",
    "age": 21,
    "courses": ["Math", "CS"],
    "graduated": False
}

# Serialize
json_str = json.dumps(data, indent=2)
print(json_str)

# Deserialize
parsed = json.loads(json_str)
print(parsed["name"])  # Alice

# Working with JSON files
with open("data.json", "w") as f:
    json.dump(data, f)

with open("data.json", "r") as f:
    loaded = json.load(f)

Learning Resources & Training

Python Training at ZN Infotech

What We Offer

  • Core Python & Advanced Concepts
  • Data Structures & Algorithms
  • Web Development with Django/Flask
  • Data Science & Machine Learning
  • Industrial Training & Internships

Contact Information

+91 9335726249

info@zninfotech.com

1st Floor, Super Complex, Kursi Road, Tedhi Pulia, Lucknow-226020

Visit Our Website

Practice Exercises

Beginner Exercises

1. Create and Access

Create a dictionary for a book with title, author, year, and price. Access each value.

# Your solution here

2. Frequency Counter

Count the frequency of each character in "hello world".

3. Merge Dictionaries

Merge two dictionaries, handling duplicate keys by summing values.

Advanced Exercises

4. Invert Dictionary

Create a function that inverts a dictionary (keys become values). Handle duplicate values.

5. Nested Dictionary Flattening

Flatten a nested dictionary, creating keys like "user.name" for nested values.

6. LRU Cache Implementation

Implement a Least Recently Used cache using OrderedDict with size limit.