Python Tutorials

Choose a lesson to begin

Dictionaries and Advanced Data Structures

Dictionaries are Python's most versatile data structure. They store key-value pairs, allowing you to organize and access data by meaningful names instead of numeric indices.

What Is a Dictionary?

A dictionary maps keys to values:

person = {
    "name": "Alice",
    "age": 30,
    "city": "New York"
}
Think of it like a real dictionary where you look up a word (key) to get its definition (value).

Creating Dictionaries

# Empty dictionary
empty = {}

With initial data

user = { "username": "alice123", "email": "alice@example.com", "verified": True }

Using dict()

settings = dict(theme="dark", volume=80, muted=False)

From pairs

pairs = [("a", 1), ("b", 2), ("c", 3)] mapping = dict(pairs) # {'a': 1, 'b': 2, 'c': 3}

Accessing Values

user = {"name": "Alice", "age": 30}

Using square brackets

print(user["name"]) # Alice

Safe access with get()

email = user.get("email") # Returns None if not found print(email) # None

With default value

phone = user.get("phone", "Not provided") print(phone) # Not provided

When to use each:

Adding and Updating

user = {"name": "Alice"}

Add new key-value pair

user["email"] = "alice@example.com"

Update existing value

user["name"] = "Alice Smith"

Add multiple at once

user.update({"age": 30, "city": "NYC"}) print(user) # {'name': 'Alice Smith', 'email': 'alice@example.com', # 'age': 30, 'city': 'NYC'}

Removing Items

user = {"name": "Alice", "age": 30, "temp": "delete me"}

Delete a key

del user["temp"]

Remove and get value

age = user.pop("age") # Returns 30 print(age)

Remove with default (doesn't crash if missing)

phone = user.pop("phone", None)

Remove last inserted item (Python 3.7+)

item = user.popitem() # Returns ("name", "Alice")

Clear everything

user.clear() # {}

Checking for Keys

user = {"name": "Alice", "age": 30}

Check if key exists

if "email" in user: print(user["email"]) else: print("No email found")

Check if key doesn't exist

if "phone" not in user: print("Phone number missing")

Get all keys

keys = user.keys() # dict_keys(['name', 'age'])

Get all values

values = user.values() # dict_values(['Alice', 30])

Iterating Through Dictionaries

user = {"name": "Alice", "age": 30, "city": "NYC"}

Loop through keys (default)

for key in user: print(key)

Loop through values

for value in user.values(): print(value)

Loop through both (most common)

for key, value in user.items(): print(f"{key}: {value}")

Output:

# name: Alice # age: 30 # city: NYC

Nested Dictionaries

Dictionaries can contain other dictionaries:

database = {
    "user1": {
        "name": "Alice",
        "email": "alice@example.com",
        "scores": [95, 87, 92]
    },
    "user2": {
        "name": "Bob",
        "email": "bob@example.com",
        "scores": [88, 90, 85]
    }
}

Access nested values

print(database["user1"]["name"]) # Alice print(database["user2"]["scores"][0]) # 88

Add nested structure

database["user3"] = { "name": "Charlie", "email": "charlie@example.com" }

Iterate nested structure

for user_id, user_data in database.items(): print(f"\n{user_id}:") for field, value in user_data.items(): print(f" {field}: {value}")

Common Patterns

Counting Occurrences

text = "the quick brown fox jumps over the lazy dog"
word_count = {}
for word in text.split():
    word_count[word] = word_count.get(word, 0) + 1
print(word_count)
# {'the': 2, 'quick': 1, 'brown': 1, 'fox': 1, ...}

Or using dict.setdefault()

word_count = {} for word in text.split(): word_count.setdefault(word, 0) word_count[word] += 1

Grouping Data

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

Group by grade

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', 'David']}

Inverting a Dictionary

original = {"a": 1, "b": 2, "c": 3}
inverted = {v: k for k, v in original.items()}
print(inverted)  # {1: 'a', 2: 'b', 3: 'c'}

Merging Dictionaries

dict1 = {"a": 1, "b": 2}
dict2 = {"c": 3, "d": 4}

Python 3.9+

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

Older Python

merged = {**dict1, **dict2}

Using update (modifies original)

dict1.update(dict2)

Advanced: defaultdict

For automatic default values, use collections.defaultdict:

from collections import defaultdict

Automatically creates empty list for new keys

groups = defaultdict(list) groups["A"].append("Alice") groups["B"].append("Bob") groups["A"].append("Alex")

No need to check if key exists!

print(dict(groups)) # {'A': ['Alice', 'Alex'], 'B': ['Bob']}

For counting

counts = defaultdict(int) for letter in "hello": counts[letter] += 1 # Starts at 0 automatically print(dict(counts)) # {'h': 1, 'e': 1, 'l': 2, 'o': 1}

Advanced: Counter

For counting, use collections.Counter:

from collections import Counter

Count items

letters = Counter("mississippi") print(letters)

Counter({'i': 4, 's': 4, 'p': 2, 'm': 1})

Most common items

words = ["apple", "banana", "apple", "cherry", "banana", "apple"] counts = Counter(words) print(counts.most_common(2)) # [('apple', 3), ('banana', 2)]

Combine counters

c1 = Counter("aab") c2 = Counter("abc") print(c1 + c2) # Counter({'a': 3, 'b': 2, 'c': 1})

Sets: Unique Collections

Sets store unique values (no duplicates):

# Create a set
fruits = {"apple", "banana", "orange"}

Remove duplicates from list

numbers = [1, 2, 2, 3, 3, 3, 4] unique = set(numbers) # {1, 2, 3, 4}

Add items

fruits.add("grape")

Remove items

fruits.remove("banana") # Crashes if not found fruits.discard("kiwi") # Safe, doesn't crash

Set operations

a = {1, 2, 3, 4} b = {3, 4, 5, 6} print(a & b) # Intersection: {3, 4} print(a | b) # Union: {1, 2, 3, 4, 5, 6} print(a - b) # Difference: {1, 2} print(a ^ b) # Symmetric difference: {1, 2, 5, 6}

Tuples: Immutable Sequences

Tuples are like lists but can't be changed:

# Create tuple
point = (10, 20)
rgb = (255, 128, 0)

Access items

x = point[0] # 10

Unpack tuple

x, y = point r, g, b = rgb

Use as dictionary keys (lists can't do this)

locations = { (0, 0): "origin", (1, 0): "east", (0, 1): "north" } print(locations[(1, 0)]) # east

Return multiple values from function

def get_stats(): return (10, 20, 30) # min, max, avg min_val, max_val, avg_val = get_stats()

Real-World Examples

User Profile System

users = {
    "alice": {
        "email": "alice@example.com",
        "age": 30,
        "premium": True,
        "login_count": 150
    },
    "bob": {
        "email": "bob@example.com",
        "age": 25,
        "premium": False,
        "login_count": 45
    }
}

Find all premium users

premium_users = [ username for username, data in users.items() if data["premium"] ] print(premium_users) # ['alice']

Inventory Management

inventory = {
    "laptop": {"price": 1200, "stock": 5},
    "mouse": {"price": 25, "stock": 50},
    "keyboard": {"price": 75, "stock": 30}
}

Check stock

item = "laptop" if inventory[item]["stock"] > 0: print(f"{item} available: ${inventory[item]['price']}") else: print(f"{item} out of stock")

Update stock

inventory["laptop"]["stock"] -= 1

Calculate total value

total_value = sum( data["price"] * data["stock"] for data in inventory.values() ) print(f"Total inventory value: ${total_value}")

Configuration Management

config = {
    "database": {
        "host": "localhost",
        "port": 5432,
        "name": "myapp"
    },
    "cache": {
        "enabled": True,
        "ttl": 3600
    },
    "logging": {
        "level": "INFO",
        "file": "/var/log/app.log"
    }
}

Access nested config

db_host = config["database"]["host"] cache_enabled = config["cache"]["enabled"]

Safe nested access

def get_config(path, default=None): """Get config using dot notation: 'database.host'""" keys = path.split(".") value = config for key in keys: if isinstance(value, dict) and key in value: value = value[key] else: return default return value print(get_config("database.host")) # localhost print(get_config("database.timeout", 30)) # 30 (default)

Try It Out!

  • Create a phone book dictionary with names and numbers
  • Count letter frequency in a sentence
  • Create a nested structure for a movie database (title, year, rating, cast)
  • Implement a simple cache using a dictionary
  • Group a list of students by their grades
  • Key Takeaways

    Dictionaries are the backbone of data organization in Python! 🐍

    🐍 Python Runner