Python Sets
Unique Collections Done Right
Master Python sets β from creation and membership to union, intersection, difference, 15+ methods, set comprehensions, frozenset, and performance. Over 50 runnable examples, each explained in depth: why it's used, how it operates, how it affects your program, and why it matters.
fruits = {"apple", "banana", "cherry", "apple"}
print(fruits)
backend = {"Python", "Go", "Rust"}
frontend = {"JavaScript", "TypeScript", "Python"}
print("Union:", backend | frontend)
{'apple', 'cherry', 'banana'}
Union: {'Python', 'Go', 'Rust', 'TypeScript', 'JavaScript'}
What you will learn
Everything about sets in Python β from creation and uniqueness to advanced operations, comprehensions, frozenset, and performance. Each concept is broken down step-by-step with interactive code examples from @PoeticGlenn.
What Is a Python Set?
A set is Python's unordered collection of unique, hashable objects β it is the language's implementation of the mathematical set. A set automatically deduplicates: you can never have two identical elements in a set. This single property makes sets the perfect tool for membership testing, removing duplicates, and performing set operations like union, intersection, and difference.
Uniqueness
Sets enforce uniqueness automatically β duplicates are silently ignored, making deduplication trivial.
O(1) Membership
Check if an item exists in constant time, regardless of set size β far faster than lists.
Set Operations
Union, intersection, difference, and symmetric difference β mathematical operations made practical.
"A set is a promise: every element is unique, and you can check membership in an instant." β @PoeticGlenn π΅
Why Every Programmer Must Master Sets
Sets are Python's implementation of the hash set β one of the most important data structures in all of computer science. They are the go-to tool for membership testing (O(1) average case), deduplication, and set-theoretic operations that appear constantly in data processing, algorithms, and real-world programming. If lists taught you to think in sequences and dictionaries taught you to think in key-value mappings, sets teach you to think in collections of distinct things.
π§Ή Deduplication
Remove duplicates from any iterable with a single line: unique = set(my_list). This is the simplest, fastest way to deduplicate data.
β‘ Fast Membership
Check if item in my_set in O(1) time β this is the primary reason sets exist and why they're so widely used.
π Set Operations
Union, intersection, difference, and symmetric difference express complex logic concisely and run efficiently.
π Hashability
Sets require hashable elements β understanding this requirement helps you design better data structures and avoid common errors.
if item not in list inside a loop over another list, that's a classic O(nΒ²) pattern that a set turns into O(n). The performance difference can be enormous for large data."
The Power of Sets in Real-World Code
Sets are how programs answer "is this item in this collection?" in constant time. That seemingly simple question β membership β appears in almost every program: checking if a username is already taken, ensuring a product isn't already in a cart, filtering duplicates from a list, finding common friends between two users. Sets make these operations fast and natural.
Data Cleaning
Deduplicate datasets, validate entries, and find anomalies β sets are the foundation of data cleaning pipelines.
Social Networks
Friend recommendations, mutual connections, and community detection all rely heavily on set operations.
Tag Management
Blog posts, products, and content categories use sets to manage tags β union, intersection, and subset checks are essential.
Sets are the tool for any problem that involves testing membership or performing set-theoretic operations.
π Table of Contents
Jump to any section β all entries are equal size
π€ Set Basics β Creation, Membership, and Uniqueness
The foundation everything else in this tutorial builds on
Curly Braces and the set() Constructor
A set is created using curly braces {} with comma-separated values, or the set() constructor. Note that empty curly braces create a dictionary, not a set β use set() for an empty set.
Step-by-step explanation:
- Step 1: Use
set()to create an empty set β{}creates a dictionary. - Step 2: Use curly braces for set literals:
{1, 2, 3}. - Step 3: The
set()constructor accepts any iterable and deduplicates automatically.
empty = set() print(empty, type(empty)) not_a_set = {} print(not_a_set, type(not_a_set)) fruits = {"apple", "banana", "cherry"} print(fruits) numbers = set([1, 2, 2, 3, 3, 3, 4]) print(numbers) letters = set("hello") print(letters)
set() constructor is one of the most useful one-liners in Python β it's the primary tool for deduplicating any iterable.The in Operator β O(1) Membership
Step-by-step explanation:
- Step 1: Use
into test membership βitem in set. - Step 2: Use
not into test absence. - Step 3: Set membership is O(1) β list membership is O(n).
colors = {"red", "green", "blue"} print(f'"red" in colors: {"red" in colors}') print(f'"yellow" in colors: {"yellow" in colors}') print(f'"green" not in colors: {"green" not in colors}') import time big_list = list(range(1000000)) big_set = set(big_list) start = time.perf_counter() result_list = 999999 in big_list list_time = time.perf_counter() - start start = time.perf_counter() result_set = 999999 in big_set set_time = time.perf_counter() - start print(f"List membership: {list_time:.6f}s") print(f"Set membership: {set_time:.6f}s")
Sets Enforce Uniqueness β Elements Must Be Hashable
Step-by-step explanation:
- Step 1: Duplicates are silently ignored.
- Step 2: Adding an existing element does nothing.
- Step 3: Set elements must be hashable β lists and other sets cannot be elements.
s = {1, 2, 2, 3, 3, 3, 4} print(s) s.add(2) print(s) try: bad = {[1, 2], [3, 4]} except TypeError as e: print(f"Error: {e}")
π Set Operations β Union, Intersection, Difference, and More
The set-theoretic operations that make sets so powerful
| Operator and .union() Method
The union of two sets contains all elements that are in either set.
Step-by-step explanation:
- Step 1:
a | breturns a new set with all elements from both sets. - Step 2:
a.union(b)does the same β accepts any iterable. - Step 3: Union is commutative and associative.
a = {1, 2, 3} b = {3, 4, 5} print(f"a | b: {a | b}") print(f"a.union(b): {a.union(b)}") c = {5, 6, 7} print(f"a.union(b, c): {a.union(b, c)}") print(f"a | b | c: {a | b | c}") print(f"a.union([10, 11, 12]): {a.union([10, 11, 12])}")
& Operator and .intersection() Method
The intersection of two sets contains only elements that are in both sets.
Step-by-step explanation:
- Step 1:
a & breturns a new set with elements present in both. - Step 2:
a.intersection(b)does the same β accepts any iterable. - Step 3: Intersection is commutative and associative.
a = {1, 2, 3, 4} b = {3, 4, 5, 6} print(f"a & b: {a & b}") print(f"a.intersection(b): {a.intersection(b)}") c = {4, 5, 6, 7} print(f"a.intersection(b, c): {a.intersection(b, c)}") print(f"a & b & c: {a & b & c}") print(f"a.intersection([3, 10, 20]): {a.intersection([3, 10, 20])}")
- Operator and .difference() Method
The difference of two sets contains elements that are in the first set but not in the second.
Step-by-step explanation:
- Step 1:
a - breturns elements inanot inb. - Step 2:
a.difference(b)does the same. - Step 3: Difference is NOT commutative β order matters.
a = {1, 2, 3, 4} b = {3, 4, 5, 6} print(f"a - b: {a - b}") print(f"a.difference(b): {a.difference(b)}") print(f"b - a: {b - a}") c = {4, 5, 6} print(f"a.difference(b, c): {a.difference(b, c)}") print(f"a.difference([3, 4]): {a.difference([3, 4])}")
a - b and b - a are usually completely different sets.^ Operator and .symmetric_difference() Method
The symmetric difference of two sets contains elements that are in exactly one of the sets.
Step-by-step explanation:
- Step 1:
a ^ breturns elements in exactly one set. - Step 2:
a.symmetric_difference(b)does the same. - Step 3: Symmetric difference is commutative.
a = {1, 2, 3, 4} b = {3, 4, 5, 6} print(f"a ^ b: {a ^ b}") print(f"a.symmetric_difference(b): {a.symmetric_difference(b)}") print(f"b ^ a: {b ^ a}") print(f"a.symmetric_difference([3, 4, 10]): {a.symmetric_difference([3, 4, 10])}")
Checking Containment Relationships
Step-by-step explanation:
- Step 1:
a.issubset(b)ora <= bchecks if all elements ofaare inb. - Step 2:
a < bchecks for a proper subset (strictly smaller). - Step 3:
b.issuperset(a)orb >= ais the reverse.
a = {1, 2, 3} b = {1, 2, 3, 4, 5} c = {1, 2, 3} print(f"a.issubset(b): {a.issubset(b)}") print(f"a.issubset(c): {a.issubset(c)}") print(f"a <= b: {a <= b}") print(f"a <= c: {a <= c}") print(f"a < b: {a < b}") print(f"a < c: {a < c}") print(f"b.issuperset(a): {b.issuperset(a)}") print(f"b >= a: {b >= a}") print(f"b > a: {b > a}") print(f"c > a: {c > a}")
.isdisjoint() β No Common Elements
a = {1, 2, 3} b = {4, 5, 6} c = {3, 4, 5} print(f"a.isdisjoint(b): {a.isdisjoint(b)}") print(f"a.isdisjoint(c): {a.isdisjoint(c)}")
.isdisjoint() is more efficient than len(a & b) == 0 because it can return False as soon as any common element is found.π Set Methods β Adding, Removing, and Updating
Every operation you'll need to modify sets
.add() and .update()
Step-by-step explanation:
- Step 1:
.add(element)inserts a single element. - Step 2:
.add()silently ignores duplicates. - Step 3:
.update(iterable)adds all elements from an iterable.
s = {1, 2, 3} s.add(4) print(s) s.add(2) print(s) s.update([5, 6, 7]) print(s) s.update({8, 9, 10}) print(s)
.remove(), .discard(), and .pop()
Step-by-step explanation:
- Step 1:
.remove(element)deletes the element β raisesKeyErrorif missing. - Step 2:
.discard(element)is safer β does nothing if missing. - Step 3:
.pop()removes and returns an arbitrary element.
s = {1, 2, 3, 4, 5} s.remove(3) print(s) try: s.remove(10) except KeyError as e: print(f"Error: {e}") s.discard(4) print(s) s.discard(10) print(s) popped = s.pop() print(f"popped: {popped} | remaining: {s}")
.discard() when you're not sure if an element exists. Use .remove() when the element must exist..clear() and .copy()
s = {1, 2, 3, 4, 5} t = s.copy() t.add(6) print(f"s: {s}") print(f"t: {t}") s.clear() print(s)
.update(), .intersection_update(), .difference_update(), .symmetric_difference_update()
a = {1, 2, 3, 4} b = {3, 4, 5, 6} a.update(b) print(a) a = {1, 2, 3, 4} a.intersection_update(b) print(a) a = {1, 2, 3, 4} a.difference_update(b) print(a) a = {1, 2, 3, 4} a.symmetric_difference_update(b) print(a)
β¨ Set Comprehensions
The concise, Pythonic way to build new sets
{expression for item in iterable if condition}
Step-by-step explanation:
- Step 1: A set comprehension creates a new set by applying an expression to each item in an iterable.
- Step 2: An optional filter condition can be added.
- Step 3: Duplicates are automatically removed.
squares_loop = set() for n in range(6): squares_loop.add(n ** 2) print(squares_loop) squares_comp = {n ** 2 for n in range(6)} print(squares_comp) even_squares = {n ** 2 for n in range(10) if n % 2 == 0} print(even_squares) words = ["apple", "banana", "kiwi", "apple"] lengths = {len(word) for word in words} print(lengths) nums = {1, 2, 3, 4, 5} doubled = {n * 2 for n in nums if n % 2 == 0} print(doubled)
βοΈ Frozenset β Immutable, Hashable Sets
Sets that can be used as dictionary keys and set members
Immutable Sets with the Same Operations
Step-by-step explanation:
- Step 1:
frozenset(iterable)creates an immutable set. - Step 2: All set operations (union, intersection, etc.) work on frozensets.
- Step 3: Mutations (add, remove) are not allowed.
- Step 4: Frozensets are hashable and can be used as dictionary keys or set members.
fs = frozenset({1, 2, 3, 4}) print(fs, type(fs)) fs2 = frozenset({3, 4, 5, 6}) print(fs | fs2) print(fs & fs2) try: fs.add(5) except AttributeError as e: print(f"Error: {e}") cache = {} cache[frozenset({1, 2, 3})] = "value" print(cache) s = {frozenset({1, 2}), frozenset({3, 4})} print(s)
βοΈ Advanced β Hashability, Performance, and Use Cases
The details that separate a working script from a well-designed one
Only Hashable Elements Can Be in a Set
valid = {"hello", 42, (1, 2), frozenset({3, 4})} print(valid) try: invalid = {[1, 2], [3, 4]} except TypeError as e: print(f"Error: {e}") try: invalid = {{1, 2}, {3, 4}} except TypeError as e: print(f"Error: {e}")
Set Operations Are Fast β O(1) Membership and O(len(s)) Unions
import time n = 100000 big_list = list(range(n)) big_set = set(big_list) start = time.perf_counter() _ = 99999 in big_list list_time = time.perf_counter() - start start = time.perf_counter() _ = 99999 in big_set set_time = time.perf_counter() - start print(f"List membership (100k): {list_time:.6f}s") print(f"Set membership (100k): {set_time:.6f}s") a = set(range(n // 2)) b = set(range(n // 2, n)) start = time.perf_counter() c = a | b union_time = time.perf_counter() - start print(f"Union of two 50k sets: {union_time:.6f}s")
πΌ Real-World Mini Projects
Three self-contained programs that combine everything above
Removing Duplicates and Finding Invalid IDs
raw_ids = [101, 102, 103, 101, 104, 105, 102, 106, 107, 105] valid_ids = {101, 102, 103, 104, 105, 106, 107, 108, 109, 110} unique_ids = set(raw_ids) print(f"Unique IDs: {unique_ids}") invalid = unique_ids - valid_ids print(f"Invalid IDs: {invalid}") missing = valid_ids - unique_ids print(f"Missing IDs: {missing}")
Finding Friends of Friends Using Set Intersection
friends = { "Alice": {"Bob", "Cara", "David"}, "Bob": {"Alice", "Cara", "Eve"}, "Cara": {"Alice", "Bob", "Frank"}, "David": {"Alice", "Eve"}, "Eve": {"Bob", "David"}, } def suggest_friends(person): if person not in friends: return set() my_friends = friends[person] suggestions = set() for friend in my_friends: if friend in friends: suggestions.update(friends[friend]) suggestions.difference_update(my_friends) suggestions.discard(person) return suggestions print(f"Suggested for Alice: {suggest_friends('Alice')}") print(f"Mutual friends of Alice and Bob: {friends['Alice'] & friends['Bob']}")
Managing Tags with Union, Intersection, and Symmetric Difference
posts = [ {"id": 1, "tags": {"python", "tutorial", "beginner"}}, {"id": 2, "tags": {"python", "advanced", "performance"}}, {"id": 3, "tags": {"tutorial", "data", "science"}}, {"id": 4, "tags": {"python", "data", "analysis"}}, ] all_tags = set() for post in posts: all_tags.update(post["tags"]) print(f"All tags: {all_tags}") common = posts[0]["tags"] & posts[1]["tags"] print(f"Common tags (post 1 & 2): {common}") unique_tags = posts[0]["tags"] ^ posts[1]["tags"] print(f"Tags in exactly one post: {unique_tags}") for post in posts: if {"python", "data"}.issubset(post["tags"]): print(f"Post {post['id']} has both tags")
β Frequently Asked Questions β Python Sets
Common questions about Python sets, answered.
What is the difference between a set and a list?
+Sets are unordered collections of unique elements with O(1) membership testing. Lists are ordered, can contain duplicates, and have O(n) membership. Use sets for uniqueness and fast membership; use lists for order and indexed access.
How do I remove duplicates from a list?
+The simplest way is unique = list(set(my_list)). This preserves no particular order. If you need to preserve order, use list(dict.fromkeys(my_list)) or a loop with a set.
Can a set contain a list?
+No β lists are mutable and unhashable, and set elements must be hashable. Use a tuple instead if you need a sequence, or a frozenset if you need a set.
What is the difference between .remove() and .discard()?
+.remove(element) raises KeyError if the element is not found. .discard(element) does nothing if the element is not found β it's the safer, more forgiving version.
Are sets ordered?
+No β sets are unordered collections. The order of elements in a set is determined by the hash table and may change. If you need an ordered unique collection, consider using a list and manually checking uniqueness, or use dict.fromkeys().
What is a frozenset?
+A frozenset is an immutable version of a set. It supports all set operations but no mutation methods. Because it's immutable, it is hashable and can be used as a dictionary key or as an element of another set.
Can I have a set of sets?
+No β regular sets are mutable and unhashable, so they cannot be elements of a set. Use a set of frozensets instead: {frozenset({1,2}), frozenset({3,4})}.
How do I check if a set is empty?
+Use if not my_set: β empty sets evaluate to False in a boolean context. You can also check len(my_set) == 0 but the not version is more Pythonic.
βοΈ Practice Exercises & Quizzes
Test your understanding with hands-on problems and multiple-choice questions
Task: Write a function that removes duplicates from a list while preserving the original order.
Example: deduplicate([1, 2, 2, 3, 3, 3, 4]) β [1, 2, 3, 4]
def deduplicate(items: list) -> list: # Your code here pass # Test print(deduplicate([1, 2, 2, 3, 3, 3, 4])) # [1, 2, 3, 4]
def deduplicate(items: list) -> list: seen = set() result = [] for item in items: if item not in seen: seen.add(item) result.append(item) return result
Task: Write a function that returns the common elements of two lists as a list.
Example: common([1, 2, 3, 4], [3, 4, 5, 6]) β [3, 4]
def common(a: list, b: list) -> list: # Your code here pass # Test print(common([1, 2, 3, 4], [3, 4, 5, 6])) # [3, 4]
def common(a: list, b: list) -> list: return list(set(a) & set(b))
Task: Write a function that returns elements that are in the first list but not in the second.
Example: missing([1, 2, 3, 4], [3, 4, 5, 6]) β [1, 2]
def missing(a: list, b: list) -> list: # Your code here pass # Test print(missing([1, 2, 3, 4], [3, 4, 5, 6])) # [1, 2]
def missing(a: list, b: list) -> list: return list(set(a) - set(b))
Multiple-Choice Questions
1. What is the time complexity of membership testing in a set?
2. Which of these can be an element of a set?
3. What does set([1, 2, 2, 3]) return?
[1, 2, 2, 3]{1, 2, 3}{1, 2, 2, 3}[1, 2, 3]4. What is the difference between .remove() and .discard()?
.remove() is faster.discard() raises an error if missing.discard() does nothing if missing5. Which operator is used for set intersection?
|&-^6. What is a frozenset?
π You've Mastered Python Sets
From creation and uniqueness to advanced operations, comprehensions, frozenset, and performance β you now have a complete understanding of Python's set data structure. You know how to deduplicate data, test membership in O(1) time, perform set-theoretic operations, and use frozensets for hashable, immutable collections.
This curriculum, crafted by @PoeticGlenn, is your definitive guide to sets in Python. Whether you're cleaning data, building algorithms, or designing systems, you have the tools to succeed.
"A set is a promise: every element is unique, and you can check membership in an instant." β Glenn Junsay Pansensoy (@PoeticGlenn)