Python Sets and Dictionaries – CS 303E, Built-in Data Structures – Study Notes
offline

Difficulty: Beginner to Intermediate | Prerequisites: Lists and tuples, basic loop syntax

Sets and dictionaries are the two built-in data structures that do not rely on positional indexing. Sets store unique, unordered elements, making them ideal for membership testing and removing duplicates. Dictionaries store key-value pairs, letting you look up data by a meaningful label rather than a position number. Both are mutable, but each has its own rules about what types of data it can hold.

TL;DR

Sets hold unique, unordered elements and are best when you need fast membership checks or want to eliminate duplicates. Dictionaries map unique keys to values, letting you look up data by a label (like a name or ID) instead of a position number. Both are mutable and iterable, but neither supports positional indexing the way lists and tuples do.


Key Terms

Set

A built-in Python data structure that stores an unordered collection of unique elements. Written with curly braces: {1, 2, 3}. An empty set must be created with set(), not {} (that creates an empty dictionary).

Think of it as a bag of items where duplicates are automatically thrown out, and nothing has a fixed position.

Dictionary (dict)

A built-in Python data structure that stores data as key-value pairs, written with curly braces: {"name": "Alice", "age": 21}. You access values by their key, not by a position number.

Think of it as a real-world dictionary: you look up a word (the key) to find its definition (the value).

Key-value pair

A single entry in a dictionary, consisting of one key mapped to one value, separated by a colon: key: value.

In simple terms, the key is the label, the value is the data attached to that label.

Union

A set operation that combines all elements from two sets, removing duplicates. Written as s1 | s2 or s1.union(s2).

Think of it as merging two groups of people into one room, counting each person only once.

Intersection

A set operation that returns only the elements found in both sets. Written as s1 & s2 or s1.intersection(s2).

Think of it as finding who is on both guest lists.

Difference

A set operation that returns elements in the first set that are not in the second. Written as s1 - s2 or s1.difference(s2). Order matters here.

Think of it as: who is on list A but not list B?

Symmetric difference

A set operation that returns elements in either set but not in both. Written as s1 ^ s2 or s1.symmetric_difference(s2).

Think of it as: who is on exactly one list, but not both?


Core Content: Sets

Properties

  • Stores an unordered collection of unique elements (no duplicates)

  • Elements must be of an immutable type (numbers, strings, tuples). You cannot put a list or another set inside a set.

  • Different types can coexist in the same set

  • Mutable: you can add and remove elements after creation

  • Iterable: you can loop over the elements with a for-each loop

  • Searching for an element in a set is more efficient than searching in a list (this matters with large data sets)

What Sets Support

  • Built-in functions: len(), sum()

  • in operator for membership testing

  • For-each iteration

  • Set operations (union, intersection, difference, symmetric difference)

  • Methods: add(), remove(), discard(), update(), clear()

What Sets Do Not Support

Because sets are unordered:

  • No indexing (my_set[0] raises a TypeError)

  • No slicing

  • No + or * operators

  • No index-based for loops (there is no meaningful index)

Set Operations

  • s1 == s2 / s1 != s2 : equality and inequality, checks whether both sets contain the exact same elements

  • s1 | s2 or s1.union(s2) : all elements from either set

  • s1 & s2 or s1.intersection(s2) : only elements in both sets

  • s1 - s2 or s1.difference(s2) : elements in s1 but not in s2

  • s1 ^ s2 or s1.symmetric_difference(s2) : elements in one set or the other, but not both

Set Methods

  • set.add(item) : adds item to the set (no effect if already present)

  • set.remove(item) : removes item; raises KeyError if not found

  • set.discard(item) : removes item if present; no error if not found (safer than remove)

  • set.update(sequence) : adds all elements from the sequence to the set

  • set.clear() : removes all elements


Core Content: Dictionaries

Properties

  • Stores data as ordered key-value pairs

  • Each key appears only once in a dictionary; multiple keys can map to the same value

  • Keys must be immutable types (strings, numbers, tuples). Values can be any type.

  • Mutable: you can add, change, and delete key-value pairs after creation

  • Iterable: you can loop over keys, values, or both

Indexing by Key

  • Access a value with dict_name[key], which returns the value associated with that key

  • This is key-based indexing, not positional. dict_name[0] looks for a key whose value is 0, not the first entry.

  • If the key does not exist, dict_name[key] raises a KeyError

Adding, Editing, and Deleting

  • Add or update: dict_name[key] = value. If the key exists, its value is replaced. If the key does not exist, a new pair is created. (This differs from lists, where assigning to a non-existent index raises an error.)

  • Delete: del dict_name[key] removes the key-value pair

The in Operator

  • key in dict evaluates to True if the key exists in the dictionary, False otherwise

  • The in operator checks keys only, not values. To search values, you would iterate or use dict.values().

Iteration

  • Method 1: iterate over keys. for var in dictionary: loops through the keys. Access the value with dictionary[var].

  • Method 2: iterate over key-value pairs. for key, value in dict_name.items(): gives you both the key and the value in each iteration.

Dictionary Methods

  • dict.get(key) : returns the value for key, or None if the key is not found (no error raised, unlike bracket notation)

  • dict.items() : returns all key-value pairs as a sequence of tuples

  • dict.keys() : returns all keys as a sequence

  • dict.values() : returns all values as a sequence

  • dict.clear() : removes all key-value pairs


Common Misconceptions

  • Students often assume {} creates an empty set. It does not. {} creates an empty dictionary. Use set() for an empty set.

  • Students sometimes think in checks dictionary values. It checks keys only. Use value in dict.values() to search values.

  • Students often confuse set.remove() and set.discard(). remove() raises an error when the item is not found; discard() does not. Reach for discard() when you are not sure the item is present.

  • Students sometimes expect dictionaries to support positional indexing like lists. Writing my_dict[0] does not give you the "first" entry; it looks for a key with the value 0.


Why It Matters / Exam Flags

  • ⚠️ Know the difference between set.remove() and set.discard(). Exams often test which one raises an error.

  • ⚠️ Be comfortable with set operations using both operator syntax (|, &, -, ^) and method syntax (.union(), .intersection(), etc.). You may be asked to produce the same result both ways.

  • ⚠️ Understand what happens when you assign to a key that already exists in a dictionary vs one that does not. This is a common source of exam questions contrasting dict behaviour with list behaviour.

  • ⚠️ Know that dict.get(key) returns None on a missing key, while dict[key] raises a KeyError. Exams test this distinction.


Quick Self-Test

  1. True or False: A set can contain duplicate elements.

False. Sets automatically discard duplicates.

  1. Fill in the blank: To create an empty set, use ___, not {}.

set().

  1. True or False: "age" in {"name": "Alice", "age": 21} evaluates to True.

True. The in operator checks keys, and "age" is a key.

  1. Fill in the blank: dict.get(key) returns ___ if the key is not found.

None.

  1. True or False: Sets support the + operator for concatenation.

False. Use the | operator or .union() to combine sets.


Practice Q&A

Q: Given s1 = {1, 2, 3, 4} and s2 = {3, 4, 5, 6}, what is the result of s1 & s2?

A: {3, 4}. The intersection returns only the elements in both sets.

Q: What is the output of len({1, 2, 2, 3, 3, 3})?

A: 3. The set discards duplicates, leaving {1, 2, 3}.

Q: Given d = {"a": 1, "b": 2}, what happens when you run d["c"] = 3?

A: A new key-value pair "c": 3 is added to the dictionary. Unlike lists, assigning to a non-existent key does not raise an error.

Q: What is the difference between dict[key] and dict.get(key) when the key does not exist?

A: dict[key] raises a KeyError. dict.get(key) returns None without raising an error.

Q: Write a loop that prints each key and its corresponding value from a dictionary called grades.

A: for key, value in grades.items(): then print(key, value)


Connections to Other Topics

Sets and dictionaries both require their keys (or elements, in the case of sets) to be immutable. This is why tuples can be dictionary keys or set elements, but lists cannot. Understanding mutability from the Lists and Tuples notes is essential here.

Dictionary iteration patterns tie directly to file I/O: when you read structured data from a file, you will often parse it into dictionaries for easy lookup.

Set operations (union, intersection, difference) appear frequently in database queries and data processing. If you go on to study SQL or data science, these concepts transfer directly.


Related Terms / Search Tags

Python set, Python dictionary, dict, key-value pair, hash table, hashable, set operations, union intersection difference, symmetric difference, set.add(), set.remove(), set.discard(), dict.get(), dict.items(), dict.keys(), dict.values(), membership testing, unordered collection, mutable, KeyError, CS 303E, intro to programming, Python data structures