Logo OnlineCBT
PYTHON Tutorial
PYTHON · LESSON 24

Dictionaries and Key-Value Data

Create, update and safely query mappings.

Level: Beginner to Advanced
Duration: ~60 Mins Deep-Dive
Updated: 26 Jul 2026

Lesson 24: Dictionaries and Key-Value Data

1. Introduction to Mapping Data Structures

In previous lessons, we analyzed sequence data structures that reference items by positional integer indices (Lists and Tuples), as well as unordered collections of unique elements (Sets). However, in modern software engineering—ranging from processing JSON web APIs to configuring application settings and building database ORMs—data is naturally organized as associations between unique identifier labels and values.

In Python, associative mapping containers are implemented using the built-in Dictionary (`dict`) data type. Dictionaries store data as key: value pairs, offering ultra-fast lookup speed, expressive data organization, and intuitive access mechanisms.


2. Deep Dive: Architectural Properties of Python Dictionaries

1. Core Properties of the `dict` Class

  • Key-Value Mapping: Every entry pairs a unique identifier Key to an associated Value object.
  • Key Hashability Requirement: Dictionary keys MUST be immutable, hashable objects (strings, numbers, tuples, or frozensets). Mutable types like lists or dictionaries cannot serve as keys!
  • Arbitrary Value Types: Dictionary values have zero type restrictions—they can store integers, floats, strings, Booleans, lists, sets, or nested dictionaries.
  • Insertion Ordered (Python 3.7+ Standard): Dictionaries maintain the exact insertion order of key-value pairs during iteration.
  • Average $O(1)$ Constant Lookups: Powered by an internal Hash Table, looking up a value by its key takes average $O(1)$ time regardless of dictionary size.
In-Memory Hash Table Mechanism: When accessing my_dict["user_id"], Python computes hash("user_id") to locate the direct memory address bucket immediately, bypassing linear $O(n)$ scanning completely.

2. Declaring Dictionaries

Dictionaries can be instantiated using curly braces {} with colon separators or via the dict() constructor function:

DICT_CREATION_DEMO.PY
# 1. Empty Dictionary Creation
empty_dict_1 = {}
empty_dict_2 = dict()

# 2. Literal Dictionary Definition
user_profile = {
    "user_id": 101,
    "username": "alice_dev",
    "role": "Admin",
    "is_active": True,
    "skills": ["Python", "Docker", "SQL"]
}

# 3. Creation using dict() Keyword Arguments
server_config = dict(host="192.168.1.1", port=8080, ssl=True)

print("User Profile Dict :", user_profile)
print("Server Config Dict:", server_config)
print("Keys Count        :", len(user_profile))
OUTPUT
User Profile Dict : {'user_id': 101, 'username': 'alice_dev', 'role': 'Admin', 'is_active': True, 'skills': ['Python', 'Docker', 'SQL']}
Server Config Dict: {'host': '192.168.1.1', 'port': 8080, 'ssl': True}
Keys Count        : 5

3. Safe Data Access and Key Inspection

1. Direct Indexing vs The Safe `.get()` Method

Accessing a missing key using direct square bracket indexing (e.g., dict["missing_key"]) triggers a fatal KeyError exception, crashing execution.

To inspect keys safely, use the .get(key, default_fallback) method. If the key exists, it returns its value; if missing, it returns None (or your custom fallback default) without raising an error!

SAFE_ACCESS_DEMO.PY
config = {"theme": "Dark", "font_size": 14}

# Direct access for guaranteed keys
print("Theme Config:", config["theme"])

# Safe access with default fallbacks for optional keys
language = config.get("language", "English")
timeout = config.get("timeout", 30)

print("Language (Fallback):", language)
print("Timeout  (Fallback):", timeout)

# Demonstrating KeyError prevention
print("Missing Key via .get():", config.get("missing_setting"))
OUTPUT
Theme Config: Dark
Language (Fallback): English
Timeout  (Fallback): 30
Missing Key via .get(): None

2. Dictionary View Objects (`.keys()`, `.values()`, `.items()`)

Python dictionaries provide dynamic view objects that reflect live changes to the dictionary:

  • .keys(): Returns an iterable view of all dictionary key identifiers.
  • .values(): Returns an iterable view of all associated value objects.
  • .items(): Returns an iterable view of (key, value) 2-element tuples, perfect for for loop iteration and unpacking!
DICT_VIEWS_ITERATION.PY
inventory_stock = {"Laptops": 15, "Monitors": 8, "Keyboards": 45}

print("=== Iterating over Key-Value Items ===")
for item_name, quantity in inventory_stock.items():
    print(f"Product: {item_name:<12} | Current Stock: {quantity:>3} units")
OUTPUT
=== Iterating over Key-Value Items ===
Product: Laptops      | Current Stock:  15 units
Product: Monitors     | Current Stock:   8 units
Product: Keyboards    | Current Stock:  45 units

4. Mutating and Updating Dictionaries In-Place

1. Assignment, `.update()`, `.setdefault()`, and Deletions

  • Direct Assignment
  • dict[key] = value
  • Creates new key-value pair or overwrites value if key exists.
  • .update(other_dict)
  • dict.update({"a": 1})
  • Batch-merges key-value pairs from another dictionary or iterable.
  • .setdefault(key, default)
  • dict.setdefault("cnt", 0)
  • Returns value if key exists. If missing, inserts key: default and returns default.
  • .pop(key, [default])
  • dict.pop("a", None)
  • Removes key and returns its value. Returns default (or raises KeyError) if missing.
  • del dict[key]
  • del dict["a"]
  • Python keyword deleting key-value pair in-place.
  • .clear()
  • dict.clear()
  • Removes all entries, resetting size to 0.
Operation Method Syntax Example Behavior Description
DICT_MUTATION_DEMO.PY
metrics = {"views": 100, "clicks": 15}

# 1. Direct key assignment / update
metrics["views"] = 105       # Overwrites existing
metrics["shares"] = 8        # Inserts new key

# 2. Batch update using .update()
metrics.update({"likes": 42, "clicks": 20})

# 3. Atomic counter init using .setdefault()
metrics.setdefault("comments", 0)

# 4. Removing key with .pop()
removed_likes = metrics.pop("likes", 0)

print(f"Popped 'likes' Value: {removed_likes}")
print("Final Mutated Dict  :", metrics)
OUTPUT
Popped 'likes' Value: 42
Final Mutated Dict  : {'views': 105, 'clicks': 20, 'shares': 8, 'comments': 0}

5. Dictionary Pattern Matching in `match-case` Statements

Introduced in Python 3.10+, Dictionary Structural Pattern Matching inspects the presence of specific key names, expected types, and nested value structures inside dictionaries dynamically!

Partial Matching Rule in Dict Patterns: Unlike list pattern matching (which matches exact lengths), dictionary patterns perform **partial matching**! A pattern like case {"status": 200, "data": payload}: matches any dictionary containing keys "status" and "data", even if extra keys exist!
MATCH_CASE_DICT_DISPATCHER.PY
def process_api_response(response_payload: dict):
    """
    Routes JSON-style dictionary payloads using Structural Pattern Matching.
    Demonstrates evaluating dictionary key-value schemas dynamically.
    """
    match response_payload:
        case {"status": 200, "data": {"user_id": uid, "role": "ADMIN"}}:
            return f"SUCCESS: Authenticated Admin user ID #{uid}."
            
        case {"status": 200, "data": {"user_id": uid}}:
            return f"SUCCESS: Authenticated Standard user ID #{uid}."
            
        case {"status": 400 | 404, "error": error_msg}:
            return f"CLIENT ERROR: Request failed -> '{error_msg}'"
            
        case {"status": 500, "error": error_msg}:
            return f"SERVER ERROR: Internal server failure -> '{error_msg}'"
            
        case _:
            return "ERROR: Unrecognized response payload schema."

# Testing dictionary pattern matching
res1 = {"status": 200, "data": {"user_id": 881, "role": "ADMIN"}, "latency_ms": 45}
res2 = {"status": 404, "error": "Resource not found"}

print(process_api_response(res1))
print(process_api_response(res2))
OUTPUT
SUCCESS: Authenticated Admin user ID #881.
CLIENT ERROR: Request failed -> 'Resource not found'

6. Frequently Asked Interview Questions with Answers

Q1: Why must dictionary keys be hashable in Python, and can a List serve as a dictionary key?
Answer: Dictionary lookups rely on an internal Hash Table. To locate key-value entries in $O(1)$ constant time, Python computes a fixed integer hash value using hash(key). Because a list is mutable and its contents can change, its hash value would change dynamically, breaking the hash table contract. Therefore, lists are unhashable and CANNOT serve as dictionary keys.
Q2: What is the difference between direct key access `dict[key]` and `dict.get(key)`?
Answer: Direct access (dict[key]) retrieves the value if the key exists, but raises a fatal KeyError exception if the key is missing. dict.get(key, default) retrieves the value if present, but safely returns None (or a custom default fallback) if the key is missing without throwing an error.
Q3: How does dictionary key-matching behave inside Python `match-case` statements?
Answer: Dictionary pattern matching performs partial structural checks. A case {"type": "event", "id": id_val}: pattern checks whether the target dictionary contains keys "type" and "id" with matching values, ignoring any additional unlisted keys present in the dictionary.
Q4: What is the purpose of `dict.setdefault(key, default)`?
Answer: .setdefault() searches for a key in a dictionary. If the key exists, it returns its value. If missing, it inserts the key with the specified default value into the dictionary and returns that default value, providing an atomic lookup-and-insert operation.
Q5: Are Python dictionary keys ordered?
Answer: Yes. Since Python 3.7+ (and CPython 3.6+ implementation detail), standard dictionaries strictly preserve the insertion order of key-value pairs during iteration and view operations.

7. Homework & Practical Assignments

Task 1: Safe Dictionary Counter & In-Place Mutation

Create a script named dict_counter_task.py inside your lesson_24 folder:

  • Define a list of word strings: words = ["python", "code", "python", "data", "code", "python"].
  • Initialize an empty dictionary named word_counts = {}.
  • Iterate through words using a for loop and update frequency counts using .setdefault() or .get().
  • Print word counts in tabular format using f-strings and .items().

Task 2: API Payload Dispatcher with `match-case`

Create a script named api_payload_task.py:

  • Define a function parse_event_payload(payload: dict).
  • Use match-case dictionary pattern matching:
    • case {"event": "PAYMENT", "amount": amt, "status": "SUCCESS"} → Return success string.
    • case {"event": "PAYMENT", "amount": amt, "status": "FAILED", "reason": msg} → Return failure alert string.
    • case {"event": "REFUND", "txn_id": tid} → Return refund process string.
    • case _ → Return unrecognized payload error.
  • Test with sample payloads and print results using f-strings.

Task 3: Comprehensive Review Project — Enterprise Customer Record OS (`customer_crm_os.py`)

Create a script named customer_crm_os.py inside your lesson_24 folder. This assignment tests and integrates **ALL concepts learned across Lessons 1 through 24**.

Project Architectural Requirements Specification:

  1. Environment, Modules & Entry Guard (Lessons 18-20):
    • Import standard modules (sys, datetime, json).
    • Wrap main execution inside an if __name__ == "__main__": guard block.
  2. Dictionaries & Data Mapping (Lesson 24):
    • Maintain a global nested dictionary registry: CUSTOMER_DATABASE = {} where keys are string User IDs (e.g., "USR_101") and values are detailed profile dictionaries.
    • Use safe access (.get(), .setdefault()) and update methods (.update(), .pop()) to mutate CRM records.
  3. Sets, Tuples & Lists (Lessons 21-23):
    • Store user security roles as set objects to perform fast permission set operations.
    • Store transactional history entries as list objects containing NamedTuple records.
  4. Functional Processing & Anonymous Lambdas (Lesson 17):
    • Filter active customer profiles using filter() and lambda functions based on account balance or status criteria.
    • Sort customer records by total spent using sorted() with custom tuple lambda keys.
  5. Advanced Parameters & Scope (Lessons 15-16):
    • Structure logic into pure modular functions accepting *args and **kwargs with type hints, docstrings, and early return Guard Clauses.
  6. Indefinite & Definite Loops (Lessons 13-14):
    • Run the interactive CLI interface inside a continuous while True menu loop.
    • Iterate through output profile reports using for loops with enumerate() and .items().
  7. Pattern Matching CLI Dispatcher (Lesson 12):
    • Process incoming user CLI command tokens inside a match-case block:
      • case ["ADD", uid, name, email, tier] → Create new user dictionary in CUSTOMER_DATABASE.
      • case ["GET", uid] → Safely fetch profile via .get() and display formatted table.
      • case ["UPDATE", uid, field_name, new_val] → Mutate nested dictionary key in-place.
      • case ["AUDIT"] → Perform set operations on customer role permissions.
      • case ["EXIT" | "QUIT"] → Terminate session safely using a sentinel flag.
      • case _ → Output command error message.
  8. Conditionals, Formatting & Foundations (Lessons 1-11):
    • Sanitize all string inputs using .strip() and .upper().
    • Format tabular reports using f-strings with field width alignment specifiers (:<15, :>10) and currency formatting (:,.2f).

8. File & Workspace Directory Structure

Standard Course Workspace Layout:

Ensure all exercise files are stored inside their corresponding lesson directories:

python_mastery_course/
│
├── lesson_01/ ... lesson_23/
│
└── lesson_24/
    ├── dict_creation_demo.py
    ├── safe_access_demo.py
    ├── dict_views_iteration.py
    ├── dict_mutation_demo.py
    ├── match_case_dict_dispatcher.py
    ├── dict_counter_task.py        <-- (Task 1)
    ├── api_payload_task.py         <-- (Task 2)
    └── customer_crm_os.py          <-- (Task 3: Master Review Capstone)
        

9. What We Will Learn Next

Next Up: Lesson 25 — List, Set and Dictionary Comprehensions

Now that you master all fundamental core data structures (Lists, Tuples, Sets, and Dictionaries), we will unlock Python's most elegant syntactic feature: Comprehensions!

In the next lesson, we will cover:

  • Writing elegant, declarative List Comprehensions ([expr for item in iterable if condition]).
  • Constructing unique collections with Set Comprehensions ({expr for item in iterable}).
  • Transforming key-value maps with Dictionary Comprehensions ({key: val for item in iterable}).
  • Replacing multi-line for loops and map()/filter() calls with readable single-line expressions.
  • Nested Comprehensions and performance benchmarks.

📝 Live Lesson Practice

HTML/CSS JavaScript Python C++ C PHP
⌨️ Practice Inputs (लाइव इनपुट भरें) (खाली होने पर RED, भरने पर GREEN underline)
💻 Code Editor (Monaco VS Code Engine)
👀 Live Preview
Address Contact

+91 7877547686

E-mail

onlinecbtportal@gmail.com

Helpline Number

+91 7877547686


Click To Download
Get it on Google Play

ऐप डाउनलोड करने
के लिए Google Play पर
उपलब्ध है

WhatsApp Chat