Python

Python Fundamentals

Sets

A set is an unordered collection of unique items — duplicates are automatically removed, and there's no indexing.

JrCodex·5 min read

Jr Codex Python Notes

Level: Beginner Prerequisites: Chapter 8 Time to complete: ~15 minutes


Table of Contents

  1. What is a Set?
  2. Creating Sets
  3. Adding & Removing Items
  4. Set Operations (Math-Style)
  5. Common Use Case: Deduplication
  6. Frozensets
  7. Summary & Next Steps

1. What is a Set?

A set is an unordered collection of unique items — duplicates are automatically removed, and there's no indexing.

numbers = {1, 2, 3, 2, 1}
print(numbers)      # {1, 2, 3} — duplicates dropped automatically
 
print(numbers[0])    # TypeError: 'set' object is not subscriptable — no order, no indexing

Sets are built on the same hashing mechanism as dictionary keys (Chapter 8) — which is why membership tests (in) on a set are extremely fast, much faster than on a list.


2. Creating Sets

fruits = {"apple", "banana", "cherry"}
empty_set = set()          # NOT {} — that creates an empty DICT!
from_list = set([1, 2, 2, 3, 3, 3])
print(from_list)             # {1, 2, 3}
 
empty_dict = {}
print(type(empty_dict))       # <class 'dict'> — the classic empty-set trap

Common pitfall: {} always creates an empty dictionary, never an empty set. Use set() explicitly.


3. Adding & Removing Items

fruits = {"apple", "banana"}
 
fruits.add("cherry")            # add one item
fruits.update(["date", "fig"])   # add multiple items
 
fruits.remove("banana")          # removes item, raises KeyError if missing
fruits.discard("mango")           # removes item, NO error if missing — safer
popped = fruits.pop()              # removes and returns an ARBITRARY item (no order!)
fruits.clear()                       # empty the set
MethodBehavior if Item Missing
.remove(x)Raises KeyError
.discard(x)Silently does nothing

4. Set Operations (Math-Style)

This is where sets earn their keep — Python implements real set theory operations:

a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
 
print(a | b)        # {1,2,3,4,5,6} — union: all items from both
print(a & b)         # {3, 4}        — intersection: items in BOTH
print(a - b)          # {1, 2}        — difference: in a, not in b
print(b - a)           # {5, 6}        — difference: in b, not in a
print(a ^ b)            # {1,2,5,6}     — symmetric difference: in one but not both
 
print(a.issubset(b))      # False — is every item of a also in b?
print({1, 2}.issubset(a))  # True
print(a.isdisjoint(b))       # False — do they share NO items?
Set Operations Visualized
─────────────────────────────────────────────
  a = {1,2,3,4}     b = {3,4,5,6}

  a | b  (union)          : 1 2 [3 4] 5 6   → {1,2,3,4,5,6}
  a & b  (intersection)   :     [3 4]        → {3,4}
  a - b  (difference)     : [1 2]            → {1,2}
  a ^ b  (symmetric diff) : 1 2       5 6    → {1,2,5,6}
─────────────────────────────────────────────
OperatorMethod EquivalentMeaning
|.union()Combine both sets
&.intersection()Only shared items
-.difference()Items in first, not second
^.symmetric_difference()Items in exactly one set

5. Common Use Case: Deduplication

The single most common reason to reach for a set in everyday code:

names = ["Alice", "Bob", "Alice", "Charlie", "Bob"]
unique_names = list(set(names))
print(unique_names)     # ['Alice', 'Bob', 'Charlie'] — order not guaranteed!
 
# Fast membership testing — much faster than `in` on a large list
allowed_users = {"alice", "bob", "charlie"}
print("alice" in allowed_users)     # O(1) average — near-instant, even with millions of items

Why sets are fast for in: a list check (x in my_list) scans item by item — O(n). A set check uses hashing to jump straight to the answer — O(1) on average. This matters once your data grows beyond toy examples (relevant again when working with large datasets in the ML modules).


6. Frozensets

A frozenset is the immutable version of a set — same operations, but no .add()/.remove(). Its main use is as a dictionary key or an item inside another set (since regular sets, like lists, aren't hashable).

fs = frozenset([1, 2, 3])
fs.add(4)          # AttributeError: 'frozenset' object has no attribute 'add'
 
# Useful when you need a set AS a dictionary key
cache = {
    frozenset([1, 2]): "computed_result_1",
    frozenset([3, 4]): "computed_result_2",
}

7. Summary & Next Steps

Key Takeaways

  • Sets store unique, unordered items — duplicates are removed automatically.
  • {} creates a dict, not a set — always use set() for an empty set.
  • Set operations (| & - ^) mirror mathematical set theory: union, intersection, difference, symmetric difference.
  • Sets give near-instant membership testing (in) — the standard tool for deduplication and fast lookups.

Concept Check

  1. Why does unique = set([1, 1, 2, 3, 3]) result in {1, 2, 3}?
  2. What's the difference between .remove() and .discard() on a set?
  3. When would you reach for a frozenset instead of a regular set?

Next Chapter

Chapter 10: Conditional Statements


Jr Codex — 1-on-1 Personalized Coaching | Back to Module Index