Beginner
Sets and Set Operations
📂 Phase 3: Lists, Tuples, Dictionaries, Sets (Days 11–15) · Python ProgrammingA set is an unordered collection that automatically eliminates duplicate values, built internally on a hash table for very fast membership testing. Sets are the natural tool whenever you care about uniqueness or need to compare two collections mathematically.
Creating a Set
fruits = {"apple", "banana", "cherry"}
numbers = {1, 2, 3, 2, 1} # duplicates are automatically dropped
print(numbers) # {1, 2, 3}
empty_set = set() # NOT {} — that creates an empty DICTIONARY instead
A very common trap: writing {} to create an empty set actually creates an empty dictionary. You must use set() explicitly to create an empty set.
Sets Have No Index
fruits = {"apple", "banana", "cherry"}
# print(fruits[0]) # TypeError — sets are unordered, so indexing is not supported
Since sets are unordered, the only reliable way to check for a specific value is membership testing with in, not indexing.
Adding and Removing Items
| Method | Effect |
|---|---|
| .add(x) | Adds a single item |
| .update(iterable) | Adds multiple items from another iterable |
| .remove(x) | Removes an item; raises KeyError if not present |
| .discard(x) | Removes an item; does NOT raise an error if missing |
fruits = {"apple", "banana"}
fruits.add("cherry")
print(fruits) # {'apple', 'banana', 'cherry'} — order is not guaranteed
fruits.discard("mango") # no error, even though "mango" was never in the set
Fast Membership Testing — A Set's Biggest Strength
big_list = list(range(1000000))
big_set = set(big_list)
# Checking membership in a set is dramatically faster than in a list
# for large collections, because of the underlying hash table
print(999999 in big_set) # very fast — near-instant lookup
print(999999 in big_list) # much slower — has to scan the entire list
Mathematical Set Operations
| Operation | Symbol | Method | Meaning |
|---|---|---|---|
| Union | | | .union() | All items from both sets |
| Intersection | & | .intersection() | Items present in BOTH sets |
| Difference | - | .difference() | Items in the first set but NOT the second |
| Symmetric Difference | ^ | .symmetric_difference() | Items in either set, but not both |
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a | b) # {1, 2, 3, 4, 5, 6} — union
print(a & b) # {3, 4} — intersection
print(a - b) # {1, 2} — difference (in a, not in b)
print(a ^ b) # {1, 2, 5, 6} — symmetric difference
A Practical Use Case: Removing Duplicates From a List
numbers = [1, 2, 2, 3, 4, 4, 4, 5]
unique_numbers = list(set(numbers))
print(unique_numbers) # [1, 2, 3, 4, 5] (order is not guaranteed to be preserved)
Converting a list to a set and back is the single most common, idiomatic way to deduplicate a list in Python — but note that this does not preserve the original order, since sets are unordered.
Set Comprehension
numbers = range(1, 11)
even_squares = {n ** 2 for n in numbers if n % 2 == 0}
print(even_squares) # {4, 16, 36, 64, 100}
frozenset — An Immutable Set
frozen = frozenset([1, 2, 3])
# frozen.add(4) # AttributeError — frozensets cannot be modified after creation
A frozenset behaves exactly like a regular set for reading and comparisons, but cannot be changed afterward — which also makes it hashable enough to be used as a dictionary key, unlike a regular set.
Interview tip: A favorite question is "How would you find common elements between two lists efficiently?" — the expected answer is to convert both lists to sets and use the intersection operator (&), since this runs in roughly O(n) time versus the O(n²) cost of comparing every element of one list against every element of the other with nested loops.