Back to Home 50+ examples Pyodide ready

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.

sets_demo.py
fruits = {"apple", "banana", "cherry", "apple"}
print(fruits)

backend = {"Python", "Go", "Rust"}
frontend = {"JavaScript", "TypeScript", "Python"}
print("Union:", backend | frontend)
$ python sets_demo.py
{'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.

@PoeticGlenn says: "If you ever catch yourself writing 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.

πŸ”€ Set Basics – Creation, Membership, and Uniqueness

The foundation everything else in this tutorial builds on

πŸ“ Creating Sets

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.
python
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)
πŸ’‘ The set() constructor is one of the most useful one-liners in Python β€” it's the primary tool for deduplicating any iterable.
πŸ” Membership Testing

The in Operator β€” O(1) Membership

Step-by-step explanation:

  • Step 1: Use in to test membership β€” item in set.
  • Step 2: Use not in to test absence.
  • Step 3: Set membership is O(1) β€” list membership is O(n).
python
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")
πŸ’‘ The O(1) membership guarantee is the primary reason sets exist in the language β€” it's a fundamental performance tool.
πŸ”’ Uniqueness & Hashability

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.
python
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}")
⚠️ Sets cannot contain lists or other sets because they are mutable and unhashable. Use tuples or frozensets instead.

πŸ”„ Set Operations β€” Union, Intersection, Difference, and More

The set-theoretic operations that make sets so powerful

πŸ”— Union

| Operator and .union() Method

The union of two sets contains all elements that are in either set.

Step-by-step explanation:

  • Step 1: a | b returns 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.
python
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])}")
πŸ”€ Intersection

& Operator and .intersection() Method

The intersection of two sets contains only elements that are in both sets.

Step-by-step explanation:

  • Step 1: a & b returns 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.
python
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])}")
βž– Difference

- 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 - b returns elements in a not in b.
  • Step 2: a.difference(b) does the same.
  • Step 3: Difference is NOT commutative β€” order matters.
python
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])}")
⚠️ Difference is NOT commutative β€” a - b and b - a are usually completely different sets.
πŸ”„ Symmetric Difference

^ 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 ^ b returns elements in exactly one set.
  • Step 2: a.symmetric_difference(b) does the same.
  • Step 3: Symmetric difference is commutative.
python
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])}")
🧩 Subset and Superset

Checking Containment Relationships

Step-by-step explanation:

  • Step 1: a.issubset(b) or a <= b checks if all elements of a are in b.
  • Step 2: a < b checks for a proper subset (strictly smaller).
  • Step 3: b.issuperset(a) or b >= a is the reverse.
python
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}")
πŸ” Disjoint

.isdisjoint() β€” No Common Elements

python
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

βž• Adding Elements

.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.
python
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)
πŸ—‘οΈ Removing Elements

.remove(), .discard(), and .pop()

Step-by-step explanation:

  • Step 1: .remove(element) deletes the element β€” raises KeyError if missing.
  • Step 2: .discard(element) is safer β€” does nothing if missing.
  • Step 3: .pop() removes and returns an arbitrary element.
python
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}")
⚠️ Use .discard() when you're not sure if an element exists. Use .remove() when the element must exist.
🧹 Clearing and Copying

.clear() and .copy()

python
s = {1, 2, 3, 4, 5}

t = s.copy()
t.add(6)
print(f"s: {s}")
print(f"t: {t}")

s.clear()
print(s)
πŸ”„ In-Place Set Operations

.update(), .intersection_update(), .difference_update(), .symmetric_difference_update()

python
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)
πŸ’‘ In-place operations modify the set directly, avoiding the creation of a new set object. Use them when you don't need to keep the original set.

✨ Set Comprehensions

The concise, Pythonic way to build new sets

✨ Comprehension Basics

{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.
python
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)
πŸ’‘ Set comprehensions combine mapping, filtering, and deduplication in one expression β€” they're the idiomatic way to build new sets from existing data.

❄️ Frozenset β€” Immutable, Hashable Sets

Sets that can be used as dictionary keys and set members

❄️ Frozenset

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.
python
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)
πŸ’‘ Frozensets are the answer to "I need a set that I can put in another set or use as a dictionary key" β€” a common need in advanced programming.
Advertisement

βš™οΈ Advanced β€” Hashability, Performance, and Use Cases

The details that separate a working script from a well-designed one

πŸ”‘ Hashability

Only Hashable Elements Can Be in a Set

python
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}")
⚠️ Sets use hash tables internally β€” every element must be hashable. Immutable types (strings, numbers, tuples of hashable elements, frozensets) are hashable. Mutable types (lists, sets, dictionaries) are not.
⚑ Performance

Set Operations Are Fast β€” O(1) Membership and O(len(s)) Unions

python
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

🧹 Project 1 – Deduplicate and Clean User IDs

Removing Duplicates and Finding Invalid IDs

python
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}")
πŸ‘₯ Project 2 – Friend Recommendations

Finding Friends of Friends Using Set Intersection

python
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']}")
🏷️ Project 3 – Tag Management

Managing Tags with Union, Intersection, and Symmetric Difference

python
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

πŸ§ͺ Exercise 1 – Remove Duplicates from a List

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
πŸ§ͺ Exercise 2 – Common Elements of Two Lists

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))
πŸ§ͺ Exercise 3 – Find Missing Elements

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))
πŸ“ Quick Quiz

Multiple-Choice Questions

1. What is the time complexity of membership testing in a set?

A) O(n)
B) O(1)
C) O(log n)
D) O(nΒ²)

2. Which of these can be an element of a set?

A) A list
B) A tuple
C) A set
D) A dictionary

3. What does set([1, 2, 2, 3]) return?

A) [1, 2, 2, 3]
B) {1, 2, 3}
C) {1, 2, 2, 3}
D) [1, 2, 3]

4. What is the difference between .remove() and .discard()?

A) .remove() is faster
B) .discard() raises an error if missing
C) .discard() does nothing if missing
D) They are the same

5. Which operator is used for set intersection?

A) |
B) &
C) -
D) ^

6. What is a frozenset?

A) An immutable set
B) A mutable set
C) A set that can only contain frozen items
D) A set that is always empty

πŸ’› 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.

50+ examples 15+ methods 1.1k+ learners

"A set is a promise: every element is unique, and you can check membership in an instant." β€” Glenn Junsay Pansensoy (@PoeticGlenn)

Advertisement