Last updated: 2026-05-21

Python dictionaries and sets

Dictionaries and sets are two of Python's most useful built-in data structures. A dictionary stores data as key-value pairs — the Python equivalent of JavaScript objects. A set stores unique values with no duplicates and no guaranteed order. Both are implemented using hash tables under the hood, which gives them very fast lookup operations regardless of how large they grow.


Dictionaries

A dictionary is an ordered (since Python 3.7), mutable collection of key-value pairs. Keys must be unique and immutable (strings, numbers, or tuples). Values can be anything.

user = {
    "name": "Wariz",
    "age": 20,
    "city": "Lagos",
    "is_active": True
}

Accessing Values

user["name"]          # "Wariz" — bracket notation
user.get("age")       # 20 — get() method
user.get("email")     # None — returns None if key doesn't exist
user.get("email", "not provided")  # "not provided" — custom default

The difference between [] and .get() is important: accessing a non-existent key with [] raises a KeyError. .get() returns None (or a default) instead — making it safer for keys you are not sure exist.

user["email"]    # ❌ KeyError: 'email'
user.get("email")  # ✅ None

Adding and Modifying Items

user["email"] = "wariz@example.com"    # Add a new key
user["age"] = 21                        # Update an existing key

Removing Items

user.pop("city")           # Removes "city" and returns its value
user.pop("phone", None)    # Returns None if key doesn't exist — no error
del user["is_active"]      # Removes "is_active" — KeyError if missing
user.clear()               # Removes all items

Checking for Keys

"name" in user          # True
"email" in user         # False
"name" not in user      # False

Dictionary Methods

Accessing Keys, Values, and Pairs

user = {"name": "Wariz", "age": 20, "city": "Lagos"}

user.keys()     # dict_keys(["name", "age", "city"])
user.values()   # dict_values(["Wariz", 20, "Lagos"])
user.items()    # dict_items([("name", "Wariz"), ("age", 20), ("city", "Lagos")])

These return view objects — they reflect changes to the dictionary in real time. Convert to a list if you need a static snapshot:

list(user.keys())    # ["name", "age", "city"]

Iterating Over a Dictionary

# Iterate over keys (default)
for key in user:
    print(key)

# Iterate over values
for value in user.values():
    print(value)

# Iterate over key-value pairs
for key, value in user.items():
    print(f"{key}: {value}")

Merging Dictionaries

defaults = {"theme": "light", "language": "en"}
settings = {"theme": "dark", "notifications": True}

# Python 3.9+ — merge operator
merged = defaults | settings
# {"theme": "dark", "language": "en", "notifications": True}

# Update in place
defaults.update(settings)
# defaults is now {"theme": "dark", "language": "en", "notifications": True}

When keys overlap, the right-hand dictionary's values take precedence.

setdefault()

Returns the value of a key if it exists. If not, inserts it with a default value:

user = {"name": "Wariz"}
user.setdefault("age", 0)     # Inserts age: 0, returns 0
user.setdefault("name", "Unknown")  # "name" already exists — returns "Wariz"

copy()

original = {"name": "Wariz", "age": 20}
copy = original.copy()    # Shallow copy

Same caveat as lists: assigning a dictionary to a new variable does not copy it.


Dictionary Comprehensions

Like list comprehensions, dictionary comprehensions provide a concise way to create dictionaries:

# {key_expression: value_expression for item in iterable}
squares = {x: x ** 2 for x in range(1, 6)}
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

With a condition:

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

Inverting a dictionary (swapping keys and values):

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

Nested Dictionaries

Dictionaries can be nested — values can themselves be dictionaries:

users = {
    "user_1": {"name": "Wariz", "age": 20},
    "user_2": {"name": "Ada", "age": 25}
}

users["user_1"]["name"]    # "Wariz"
users["user_2"]["age"]     # 25

Sets

A set is an unordered collection of unique values. Sets are mutable but their items must be immutable (no lists or dictionaries as set items). Because sets are unordered, they do not support indexing or slicing.

colours = {"red", "green", "blue"}
numbers = {1, 2, 3, 3, 4, 4, 5}    # Duplicates are automatically removed
print(numbers)    # {1, 2, 3, 4, 5}

Creating an Empty Set

empty_set = set()    # ✅ Correct
empty_dict = {}      # ❌ This creates an empty dictionary, not a set

Adding and Removing Items

colours = {"red", "green", "blue"}

colours.add("yellow")          # Add a single item
colours.update(["pink", "purple"])  # Add multiple items

colours.remove("red")          # Removes "red" — KeyError if not found
colours.discard("orange")      # Removes if present — no error if not found
colours.pop()                  # Removes and returns an arbitrary item
colours.clear()                # Removes all items

Membership Testing

Sets have O(1) lookup — checking membership is extremely fast regardless of the set's size. This is one of the primary reasons to use a set over a list when you need to check for existence:

allowed = {"admin", "editor", "moderator"}

"editor" in allowed     # True — very fast
"viewer" not in allowed # True

Set Operations

Sets support the classical mathematical set operations:

Union — all items from both sets

a = {1, 2, 3}
b = {3, 4, 5}

a | b              # {1, 2, 3, 4, 5}
a.union(b)         # Same result

Intersection — items present in both sets

a & b              # {3}
a.intersection(b)  # Same result

Difference — items in a but not in b

a - b              # {1, 2}
a.difference(b)    # Same result

Symmetric Difference — items in either but not both

a ^ b                        # {1, 2, 4, 5}
a.symmetric_difference(b)    # Same result

Subset and Superset

{1, 2}.issubset({1, 2, 3})      # True — {1, 2} is a subset of {1, 2, 3}
{1, 2, 3}.issuperset({1, 2})    # True
{1, 2}.isdisjoint({3, 4})       # True — no items in common

Practical Use Cases for Sets

Removing duplicates from a list

numbers = [1, 2, 2, 3, 3, 3, 4]
unique = list(set(numbers))
print(unique)    # [1, 2, 3, 4] — order not guaranteed

Fast membership testing

# List lookup — O(n), slower for large collections
allowed_list = ["admin", "editor", "moderator"]
"editor" in allowed_list    # Scans the list

# Set lookup — O(1), always fast
allowed_set = {"admin", "editor", "moderator"}
"editor" in allowed_set     # Hash lookup — nearly instant

Finding common or unique items between two collections

team_a = {"Wariz", "Ada", "Aliyu"}
team_b = {"Ada", "Bola", "Chidi"}

both_teams = team_a & team_b     # {"Ada"} — in both
only_a = team_a - team_b         # {"Wariz", "Aliyu"} — only in A
all_members = team_a | team_b    # All five members

Tuples — Immutable Sequences

While tuples are covered more fully in the Python-Specific Features topic, they are closely related to lists and worth introducing here. A tuple is an immutable, ordered sequence — once created, its contents cannot be changed.

coordinates = (40.7128, -74.0060)
rgb = (255, 0, 128)
single = (42,)    # Trailing comma required for a single-item tuple

Tuples support the same indexing and slicing as lists, but none of the modification methods (append, remove, etc.).

Tuples are commonly used for:

  • Fixed data that should not change (coordinates, RGB values, database rows).
  • Returning multiple values from a function (Python implicitly packs them into a tuple).
  • Dictionary keys (lists cannot be dictionary keys; tuples can).

Summary

Dictionary Methods

MethodWhat It Does
d[key]Access value — KeyError if missing
d.get(key, default)Access value — returns default if missing
d[key] = valueAdd or update a key
d.pop(key)Remove and return value
del d[key]Remove key — KeyError if missing
d.keys()Returns all keys
d.values()Returns all values
d.items()Returns all key-value pairs
d.update(other)Merges another dict in place
d1 | d2Returns merged dict (Python 3.9+)
d.setdefault(key, val)Insert key with default if not present
d.copy()Shallow copy
d.clear()Remove all items

Set Methods

MethodWhat It Does
s.add(item)Add a single item
s.update(iterable)Add multiple items
s.remove(item)Remove item — KeyError if missing
s.discard(item)Remove item — no error if missing
s.pop()Remove and return arbitrary item
s | tUnion
s & tIntersection
s - tDifference
s ^ tSymmetric difference
s.issubset(t)True if s is a subset of t
s.issuperset(t)True if s is a superset of t
s.isdisjoint(t)True if s and t share no items