Scrollable Nav Bar

Python Dictionaries

Dictionaries are one of the most powerful and flexible data structures in Python. Where lists are great for ordered collections, dictionaries shine when you need to associate names with values — think of them as fast, in-memory lookup tables. In practical applications you’ll use dictionaries to represent records, configuration settings, frequency counters, inverted indices, JSON-like structures received from APIs, and much more.

This article dives deeper than a quick reference: each section explains not only how the language feature works, but why it behaves that way and how to use it safely and idiomatically in real code. Code examples are included and you’ll find small suggestions for screenshots so you can illustrate the examples in your tutorial or blog post.


What is a Dictionary in Python?

A dictionary (dict) is an unordered collection of key–value pairs. Each key maps to a value, and keys must be hashable (immutable types like strings, numbers, or tuples). Unlike lists, where you access items by integer positions, dictionaries let you access values by meaningful names — this makes your code clearer and your lookups very fast.

Dictionaries are commonly used to represent objects or records: for example, a user might be expressed as {"name": "Asha", "age": 26, "email": "asha@example.com"}. The mapping structure also mirrors JSON, which is why dictionaries are ubiquitous when working with web APIs.

Example

animals = {
    "a": "aardvark",
    "b": "bison",
    "c": "cat",
}

print(animals["a"])  # aardvark

[ run this snippet in a REPL or editor and capture the output]


Creating Dictionaries

You create dictionaries using curly braces {} with key: value pairs separated by commas. The syntax is concise and readable, and Python accepts a trailing comma after the last pair — a small convenience that improves editability.

A trailing comma is purely stylistic and has practical benefits: when adding or removing lines during development it reduces the chance of syntax errors and creates cleaner diffs in version control. For multi-line literal structures (large dicts, lists, or tuples) many teams prefer to include the trailing comma.

Example :

animals = {
    "a": "aardvark",
    "b": "bison",
    "c": "cat",
}

[ show the dictionary in an editor with a trailing comma and one without for comparison]


Accessing Values Using Keys

Accessing a value is straightforward using square brackets and the key: animals["a"]. This syntax is deliberately strict — if the key does not exist Python raises a KeyError. That behavior is helpful when you want bugs to fail fast; it surfaces missing data early during development.

However, in many real-world situations you deal with optional fields or incomplete data. For those cases you’ll usually prefer safer methods (covered in the get() section) or explicit existence checks. Also remember that keys must be hashable: mutable types such as lists are not allowed as keys.

Example:

# direct access (raises KeyError if missing)
print(animals["a"])  # works

# risky access — not recommended without checks
# print(animals["e"])  # KeyError

Adding Dictionary Values

You can add a new key–value pair to a dictionary by simply assigning a value to a key that does not exist. Python will create the key automatically and store the value.

Example:

animals["d"] = "dog"  # add new key-value pair

[show dictionary before and after adding the new key]

Updating Dictionary Values

To update an existing key, assign a new value to that key. This will replace the previous value with the new one without affecting other entries.

Example:

animals["a"] = "antelope"  # update existing key

[show dictionary before and after updating the value]


Getting All Keys and Values

The keys() and values() methods return view objects (dict_keys, dict_values) rather than lists. These views are dynamic: if the underlying dictionary changes, the view reflects those changes. That can be convenient (no need to re-create the view) but it also means you should convert to a list if you need a stable snapshot for indexing, slicing, or sorting.

Example:

k_view = animals.keys()
print(k_view)            # dict_keys(['a', 'b', 'c', 'd'])

k_list = list(k_view)    # snapshot copy

Why not a list by default? Views avoid the cost of copying large datasets and make it clearer when you only need to iterate through current keys or values.


Converting Keys or Values to a List

Sometimes you need a concrete list rather than a dynamic view — for example to index, slice, sort, or hold a stable snapshot of keys or values. Convert a view to a list using list():

Example:

keys_list = list(animals.keys())
values_list = list(animals.values())

Sorting:

You can also sort while converting:

sorted_keys = sorted(animals.keys())
sorted_values = sorted(animals.values())

If you need the (key, value) pairs as a list, convert items():

items_list = list(animals.items())  # [('a', 'antelope'), ('b', 'bison'), ...]

A quick reminder: dictionary view objects (dict_keys, dict_values, dict_items) reflect the current state of the dictionary. If you need a stable snapshot that won’t change when the dict mutates, convert the view to a list.

[show list() conversion and sorted output]


Safer Lookups with dict.get()

get() is the canonical way to access keys when the key might be missing. It avoids a KeyError by returning None (or a provided default) if the key is absent — making your code more robust when consuming external or optional data.

Use get() for configuration lookups, optional fields, or cases where you have a sensible fallback. For situations where you absolutely must ensure the key exists, prefer direct indexing to intentionally raise an error and fail fast.

Example:

print(animals.get("e"))               # None
print(animals.get("e", "elephant")) # elephant

[ show code that demonstrates both behaviors side-by-side]


Measuring Dictionary Size with len()

len(dict) returns the number of keys stored in the dictionary. This is useful for quick sanity checks, assertions in tests, and small-control flows in scripts.

Example:

print(len(animals))  # number of keys<br>

Because dictionaries map keys to values, len() tells you how many entries (pairs) exist, not the total memory used or the combined size of the values.


Dictionary of Lists

A common pattern is to use a dictionary where each value is a list — for example grouping words by their first letter, or building inverted indices for simple search. This structure is expressive but introduces a common pain point: you must ensure the list exists before appending.

Example problems show up in log parsing, bucketing items, and when aggregating events. The canonical defensive pattern looks like:

Example:

if "c" not in animals:
    animals["c"] = []
animals["c"].append("cat")

This pattern works but becomes verbose when repeated often; that’s where defaultdict (or setdefault) helps.

[capture a short example that builds grouped lists from input words]


defaultdict

defaultdict from the collections module simplifies the dictionary-of-lists pattern by automatically creating default values on first access. When you construct a defaultdict you pass a callable (like list) — not an instance — which defaultdict calls to create the initial value for missing keys.

This idiom eliminates boilerplate checks and expresses intent clearly: you want a mapping whose values start life as empty lists.

from collections import defaultdict
animals = defaultdict(list)
animals["e"].append("elephant")

Be mindful that merely accessing a missing key will create it in the dictionary. If you only want a non-destructive check, use in or get() instead.


Iterating Through a Dictionary

Iteration patterns are simple and expressive. Use a plain for key in dict: to iterate keys, for v in dict.values(): for values, and for k, v in dict.items(): when you need both. Choose the smallest, clearest form that expresses your intent.

If you need a stable order, remember that since Python 3.7 insertion order is preserved in dictionaries — but relying on this property for algorithmic correctness is different from using it for display or reporting.

for key, value in animals.items():
    print(f"{key} -> {value}")

[ loop example output]


Quick Tips You’ll Use Often

  • Remove an item safely with pop(key, default) to avoid KeyError.
  • Use del dict[key] when you want an exception raised for missing keys.
  • Use dictionary comprehensions to construct maps concisely: {n: n*n for n in range(1, 6)}.
  • For thread-safe or atomic updates across multiple workers, use proper synchronization or an external store (Redis, database) rather than relying on plain dict mutation.
removed = animals.pop("b", None)

Practice Exercises

  1. Create a student dictionary with name, age, and course. Print the course value and assert the student is over 18.
  2. Use get() to read an optional grade key and provide a default of 'N/A'.
  3. Build a dictionary that groups words by their first letter. First implement it using manual checks, then simplify using defaultdict(list) and compare the two approaches.
  4. Write a function that receives a dictionary and returns a list of key: value strings sorted by key.

Summary

Dictionaries are essential building blocks in Python programming. They offer fast lookups, clear semantics for named data, and flexible patterns for aggregation and transformation. Learn the idioms (get(), defaultdict, comprehensions) and you’ll be able to model most structured data cleanly and concisely.

Practice the exercises above and add screenshots to your tutorial where indicated — readers benefit greatly from seeing the code run and the output that follows.