Sets
Reviewed & published by Brayan K
A set is Python's collection of unique items. Drop duplicates in and they silently disappear; ask "is this here?" and you get an answer almost instantly. Sets are the right tool whenever uniqueness or fast membership matters.
Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
They also bring the elegant math of unions, intersections, and differences — perfect for comparing two groups of things.
What You'll Learn in This Lesson
- Creating sets and why {} is NOT an empty set
- Automatic de-duplication of values
- Lightning-fast membership tests with 'in'
- Adding and removing items: add, remove, discard
- Set math: union, intersection, difference
- When a set beats a list (and when it doesn't)
1 Creating a Set
Write a set with curly braces and commas, or build one from any iterable with set(). Duplicates are removed on the spot:
colors = {"red", "green", "blue"}
print(colors) # {'red', 'green', 'blue'} (order may vary)
# Duplicates vanish automatically
nums = {1, 2, 2, 3, 3, 3}
print(nums) # {1, 2, 3}
# Build a set from a list to de-duplicate it
votes = ["yes", "no", "yes", "yes", "no"]
unique_votes = set(votes)
print(unique_votes) # {'yes', 'no'}
# A set from a string = its unique characters
print(set("mississippi")) # {'m', 'i', 's', 'p'}⚡ The Superpower: Instant Membership Tests
The single biggest reason to use a set is speed. Checking x in some_set is roughly constant time no matter how big the set is, while the same check on a list scans every element:
allowed_users = {"alice", "bob", "carol"}
print("alice" in allowed_users) # True (instant)
print("dave" in allowed_users) # False (instant)
print("dave" not in allowed_users) # True
# Real use: a blocklist checked thousands of times
banned_ips = {"10.0.0.5", "10.0.0.9", "192.168.1.1"}
incoming = "10.0.0.9"
if incoming in banned_ips:
print(f"Blocked {incoming}") # Blocked 10.0.0.9If your program repeatedly asks "have I seen this before?" or "is this in the allowed list?", store the values in a set. For a large collection the difference is the gap between instant and noticeably slow.
2 Adding and Removing Items
Sets are mutable — you can change their contents (even though the elements must be immutable):
tags = {"python", "code"}
tags.add("tutorial") # add one item
print(tags) # {'python', 'code', 'tutorial'}
tags.add("python") # adding a duplicate does nothing
print(len(tags)) # 3
tags.update(["web", "css"]) # add several at once
print(len(tags)) # 5
tags.remove("css") # remove — ERROR if missing
tags.discard("nope") # discard — safe, no error if missing
popped = tags.pop() # remove & return an arbitrary item
tags.clear() # empty it completely
print(tags) # set()3 Set Math: Union, Intersection, Difference
This is where sets shine. Comparing two groups of things becomes a single, readable operation:
frontend = {"alice", "bob", "carol"}
backend = {"bob", "carol", "dave"}
# Union — everyone in either team (| or .union())
print(frontend | backend) # {'alice', 'bob', 'carol', 'dave'}
# Intersection — people on BOTH teams (& or .intersection())
print(frontend & backend) # {'bob', 'carol'}
# Difference — frontend-only people (- or .difference())
print(frontend - backend) # {'alice'}
# Symmetric difference — in exactly one team (^)
print(frontend ^ backend) # {'alice', 'dave'}# Compare two readers' book lists
ada_books = {"Dune", "1984", "Hobbit", "Sapiens"}
ben_books = {"1984", "Sapiens", "Foundation"}
# Books both have read
both = ada_books & ben_books
print("Both read:", both)
# Recommend Ada's books that Ben hasn't read
for_ben = ada_books - ben_books
print("Suggest to Ben:", for_ben)
# The complete combined library
library = ada_books | ben_books
print("Total unique books:", len(library))
# Expected output:
# Both read: {'1984', 'Sapiens'}
# Suggest to Ben: {'Dune', 'Hobbit'}
# Total unique books: 5🧰 The Classic De-duplication Pattern
One of the most common real uses of a set is to remove duplicates from a list in a single line:
emails = [
"a@x.com", "b@x.com", "a@x.com", "c@x.com", "b@x.com"
]
# Remove duplicates (order NOT preserved)
unique = list(set(emails))
print(len(unique)) # 3
# Keep first-seen ORDER while de-duplicating (Python 3.7+)
seen = set()
ordered_unique = []
for e in emails:
if e not in seen:
seen.add(e)
ordered_unique.append(e)
print(ordered_unique) # ['a@x.com', 'b@x.com', 'c@x.com']list(set(items)) is the quick way, but it scrambles order. The "seen" pattern is the standard idiom when you need uniqueness and the original ordering.
🧩 Reorder Challenge
These lines should find how many tags two articles share. Reorder them so the final output is Shared tags: 2.
A) shared = a & b
B) a = {"python", "web", "api"}
C) print(f"Shared tags: {len(shared)}")
D) b = {"web", "api", "css"}B → D → A → C
a = {"python", "web", "api"} # B
b = {"web", "api", "css"} # D
shared = a & b # A -> {'web', 'api'}
print(f"Shared tags: {len(shared)}") # C -> Shared tags: 2Why: both sets a (B) and b (D) must exist before the intersection a & b (A) can run. The print (C) reports the size of that result. The two common tags are web and api.
🧠 Quick Recall
print(len({1, 2, 2, 3, 3, 3}))3 — sets discard duplicates, leaving only {1, 2, 3}, which has length 3.
2. What is the result?
print({1, 2, 3} & {2, 3, 4}){2, 3} — the & operator returns the intersection: only the elements present in both sets.
3. What is type(x)?
x = {}
print(type(x))<class 'dict'> — empty curly braces make a dictionary, not a set. Use set() for an empty set.
📋 Set Operations Cheat Sheet
| Operation | Meaning | Example |
|---|---|---|
| x in s | Membership (fast) | 2 in {1,2} → True |
| s.add(x) | Insert one item | s.add(5) |
| a | b | Union | All items from both |
| a & b | Intersection | Items in both |
| a - b | Difference | In a, not in b |
| list(set(x)) | De-duplicate | Drop repeats |
🎯 Mini Challenge: Find Common Friends
Given two people's friend lists, find mutual friends and friend suggestions.
# 🎯 YOUR TURN: social network logic with sets
maya_friends = {"sam", "leo", "nina", "kai"}
omar_friends = {"leo", "kai", "tess", "zoe"}
# Mutual friends
mutual = maya_friends & omar_friends
print("Mutual friends:", mutual)
# Suggest Omar's friends that Maya doesn't know yet
suggestions = omar_friends - maya_friends
print("Suggest to Maya:", suggestions)
# Everyone in the combined circle
everyone = maya_friends | omar_friends
print("Total people:", len(everyone))Lesson complete — sets are in your toolkit!
You can create sets, de-duplicate data, run instant membership tests, add and remove items, and use union, intersection, and difference to compare groups. Remember: set() for empty, not {}.
Practice quiz
What is the defining feature of a Python set?
- It keeps items sorted
- It allows duplicates
- It stores only unique items
- It is indexed by position
Answer: It stores only unique items. A set is an unordered collection that automatically removes duplicates.
What does len({1, 2, 2, 3, 3, 3}) return?
- 3
- 6
- 1
- 2
Answer: 3. Duplicates are discarded, leaving {1, 2, 3}, which has length 3.
How do you create an EMPTY set?
- {}
- []
- ()
- set()
Answer: set(). {} creates an empty dict; use set() for an empty set.
What does {1, 2, 3} & {2, 3, 4} produce?
- {1, 2, 3, 4}
- {2, 3}
- {1, 4}
- {1}
Answer: {2, 3}. The & operator is intersection: only items in both sets, {2, 3}.
Which operator gives the UNION of two sets?
- |
- &
- -
- ^
Answer: |. The | operator returns the union — all items from both sets.
What does a - b compute for two sets?
- Items in both
- Items in either
- Items in a but not b
- Items in neither
Answer: Items in a but not b. The - operator is the difference: items in a that aren't in b.
Why is 'x in my_set' faster than 'x in my_list' for large data?
- Sets are sorted
- Sets use a hash table (O(1) lookup)
- Lists are immutable
- Sets are smaller
Answer: Sets use a hash table (O(1) lookup). Sets are hash-table backed, giving roughly O(1) membership tests vs O(n) for lists.
What's the difference between remove() and discard()?
- No difference
- discard() raises KeyError, remove() does not
- remove() adds items
- remove() raises KeyError if missing, discard() does not
Answer: remove() raises KeyError if missing, discard() does not. remove() raises a KeyError when the item is absent; discard() is silent.
What is type({}) in Python?
- set
- dict
- list
- tuple
Answer: dict. Empty curly braces create a dictionary, not a set.
Which one-liner removes duplicates from a list called items?
- sorted(items)
- items.unique()
- list(set(items))
- set.remove(items)
Answer: list(set(items)). list(set(items)) dedupes by converting to a set and back (order not preserved).
Continue this course
- Previous: String Methods
- Next: Tuples — Immutable sequences, tuple unpacking, and when to use them over lists
- Quick reference: Python cheat sheet › Dicts & Sets
Frequently asked questions
What is a set and how is it different from a list?
A set is an unordered collection that automatically removes duplicates. Unlike a list, you can't index into a set (there's no s[0]) and the order isn't guaranteed. In exchange you get instant membership tests and built-in math operations like union and intersection.
Why is 'x in my_set' so much faster than 'x in my_list'?
Sets are backed by a hash table. Checking membership is roughly O(1) — Python jumps straight to where the value would live. A list has to scan element by element, which is O(n). For large collections of unique values you want to check repeatedly, a set is dramatically faster.
How do I create an empty set?
Use set(), not {}. Writing {} creates an empty dictionary because Python reserved that syntax for dicts first. So empty_set = set() and empty_dict = {}. Once a set has items you can write {1, 2, 3}.
Can a set contain a list or another set?
No — set elements must be hashable (immutable). Numbers, strings, and tuples work; lists, dicts, and other sets do not and raise a TypeError. If you need a set of sets, use frozenset, the immutable cousin of set, as the inner elements.
When should I reach for a set instead of a list?
Use a set when you care about uniqueness, need fast membership checks, or want set algebra (which users are in both groups? which tags are new?). Use a list when order matters, you need duplicates, or you index by position. Converting list(set(items)) is the classic one-liner to dedupe.