Q1Which of the following correctly creates a set?
How to Use Python Sets (set)
Get to know the Python set type — a duplicate-free, unordered collection — and use it for dedup and fast membership checks in your browser.
What is a set — no duplicates, no order
A set (set) is, like list and tuple, a type for grouping multiple values together. But it has two rules that make it very different.
- Each value can only appear once (duplicates are removed automatically)
- Order is not preserved (position has no meaning)
Even if you include the same value twice, only one copy remains in the final set.
(In this example, a ends up as one.)
Declare one by wrapping values in { and }, separated by commas.
For an empty set, use set() instead of {}. Writing {} gives you an empty dict.
# Duplicates are removed automatically
set_a = {"a", "b", "c", "d", "a"}
print(set_a) # {'a', 'b', 'c', 'd'} (order depends on the environment)
print(type(set_a)) # <class 'set'>
print(len(set_a)) # 4 (the duplicate 'a' collapses into one)
# Mixing numbers and other types is fine
mixed = {1, "apple", 3.14}
# Use set() for an empty set
empty_set = set()
empty_dict = {} # this becomes an "empty dict"
print(type(empty_set)) # <class 'set'>
print(type(empty_dict)) # <class 'dict'>
# Use in / not in to check membership
print("a" in set_a) # True
print("z" not in set_a) # True
No order, so no index access
Since a set has no order, you can't use index access like set_a[0] (you'll get a TypeError). If you need the N-th element, convert to list or tuple first and take it from there. Pick by use case: list / tuple when order matters, set when it doesn't.
Adding and removing elements
A set is a mutable type, so you can add and remove elements after declaring it.
The five methods you'll use most are shown below.
| Method | Role | Note |
|---|---|---|
| add(x) | Add element x | Does nothing if already present (duplicates ignored) |
| remove(x) | Remove element x | KeyError if x is missing |
| discard(x) | Remove element x | No error even if x is missing |
| pop() | Remove and return any one element | Which one is picked is not specified |
| clear() | Remove all elements | Leaves an empty set |
fruits = {"apple", "banana", "lemon"}
# add
fruits.add("grape")
fruits.add("apple") # already present, ignored
print(fruits) # {'apple', 'banana', 'lemon', 'grape'}
# remove (errors if missing)
fruits.remove("banana")
# fruits.remove("melon") # KeyError
# discard stays quiet even if missing
fruits.discard("melon") # nothing happens
print(fruits) # {'apple', 'lemon', 'grape'}
# Remove and return one arbitrary element
picked = fruits.pop()
print(picked) # some element (varies each run)
# Clear everything
fruits.clear()
print(fruits) # set()
Use remove when you want to know if the value wasn't there (it raises an error).
Use discard when you just want to delete if present and don't care otherwise.
Set operations — union, intersection, difference, symmetric difference
The biggest feature of set is set operations. You can combine two sets to pull out common elements, or elements that appear in only one of them, in a single line. You could do the same with a for loop over lists, but sets are far faster.
- Union — every element that appears in either set
- Intersection — only elements that appear in both
- Difference — elements in
sbut not int - Symmetric difference — elements that appear in exactly one of the two
The diagram below shows the results when s = {a, b, c, d} and t = {c, d, e, f}.
Operators (| & - ^) and methods (union etc.) are equivalent — use either.
s = {"a", "b", "c", "d"}
t = {"c", "d", "e", "f"}
# Union
print(s | t) # {'a', 'b', 'c', 'd', 'e', 'f'}
print(s.union(t)) # same
# Intersection
print(s & t) # {'c', 'd'}
print(s.intersection(t)) # same
# Difference (in s, not in t)
print(s - t) # {'a', 'b'}
print(s.difference(t)) # same
# Symmetric difference (in exactly one)
print(s ^ t) # {'a', 'b', 'e', 'f'}
print(s.symmetric_difference(t)) # same
Subset checks (aside)
a <= b or a.issubset(b) tells you whether every element of a is in b, returning True / False. The other direction is a >= b or a.issuperset(b).
This is used for checks like "does the user's permission set contain all the required permissions?". At first, focus on the four set operations and reach for these when you actually need them.
Real-world patterns — dedup and fast membership checks
Finally, let's nail down two go-to patterns that come up constantly in real work.
list(set(...)) — "convert to a set to drop duplicates, then back to a list" — is the common idiom.
One line, fast, and much cleaner than a for loop with a seen-check.
# Pattern ①: dedup
numbers = [1, 2, 2, 2, 3, 4, 4, 5, 6, 6]
unique_numbers = list(set(numbers))
print(unique_numbers) # [1, 2, 3, 4, 5, 6] (order may vary)
# Pattern ②: fast membership check
# x in set is much faster than x in list
allowed_users = {"alice", "bob", "carol"}
print("alice" in allowed_users) # True
print("dan" in allowed_users) # False
Why in is fast on a set
A set is backed by a hash table. It looks up values directly via their hash, so lookups take roughly constant time regardless of size.
in on a list compares elements one by one from the start, so it gets slower as the list grows. If you're going to check membership many times, convert to a set first and you'll get a dramatic speed-up.
In this article, you've seen the traits of set (no duplicates, no order), its add/remove methods, the four set operations, and the two real-world patterns — deduplication and fast membership checks.
"I don't care about order, I just want the unique ones" / "I'm checking membership over and over" / "I need the overlap of two sets" — if any of those fits, it's time to reach for set.
Knowledge Check
Answer each question one by one.
Q2Given s = {1, 2, 3}, what happens when you run s.discard(99)? (99 is not in the set)
Q3With s = {1, 2, 3, 4} and t = {3, 4, 5, 6}, what is the result of s & t?