LearnContact
Lesson 1725 min read

Sets

Learn how Python sets store unique, unordered collections of items and how to combine them using union, intersection, and difference operations.

Introduction

So far you have worked with lists and tuples, which keep items in order and allow duplicates. Python's set type takes a completely different approach: it stores an unordered collection of unique items, with no duplicates allowed.

Sets are perfect whenever you care about "does this item exist?" rather than "what position is this item at?" — things like removing duplicate values, checking membership quickly, or comparing two collections mathematically.

What You Will Learn
  • How to create sets and why order and duplicates do not apply.
  • How to add, remove, and check for elements.
  • How to combine sets using union, intersection, difference, and symmetric_difference.
  • The difference between set methods and set operators (| & - ^).
  • How to use frozenset and deduplicate a list quickly.

Creating Sets

A set is written using curly braces {} with items separated by commas, or by calling the set() function. Sets automatically drop duplicate values and do not preserve insertion order.

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

empty_set = set()
print(type(empty_set))

numbers = set([1, 2, 3, 2, 1])
print(numbers)
Output
{'banana', 'cherry', 'apple'}
<class 'set'>
<class 'set'>
{1, 2, 3}
Empty Set Gotcha

Writing {} does NOT create an empty set — it creates an empty dictionary. Always use set() to create an empty set.

Because sets are unordered, printing the same set twice may show items in a different arrangement than you typed them, and you cannot access items using an index like fruits[0].

Why Sets Are Useful

Sets exist to solve two problems extremely efficiently: removing duplicates and checking whether something exists in a collection.

No Duplicates

Adding the same value twice has no effect — a set silently keeps only one copy.

Fast Membership Testing

Checking "x in my_set" is much faster than "x in my_list" for large collections.

Mathematical Operations

Sets support union, intersection, and difference, just like sets in math class.

Easy Cleanup

Converting a list to a set instantly removes every duplicate value.

membership_speed.py
visited_pages = {"home", "about", "contact"}

print("about" in visited_pages)
print("pricing" in visited_pages)
Output
True
False

Adding & Removing Elements

Sets provide several methods for adding and removing items. Choosing the right removal method matters, because some raise an error if the item is missing and some do not.

add(item)

Inserts a single item into the set.

remove(item)

Removes an item; raises KeyError if it is not present.

discard(item)

Removes an item if present; does nothing (no error) if it is missing.

pop()

Removes and returns an arbitrary item from the set.

clear()

Removes every item, leaving an empty set.

add_remove.py
colors = {"red", "green", "blue"}

colors.add("yellow")
print(colors)

colors.remove("red")
print(colors)

colors.discard("purple")  # no error even though "purple" isn't in the set
print(colors)

popped = colors.pop()
print("Popped:", popped)
Output
{'red', 'green', 'blue', 'yellow'}
{'green', 'blue', 'yellow'}
{'green', 'blue', 'yellow'}
Popped: green
remove() vs discard()

Use discard() when you are not sure whether the item exists, so your program does not crash. Use remove() when the item should always be there and a missing item would signal a bug.

Set Operations

Sets support the classic mathematical operations you may remember from Venn diagrams: union, intersection, difference, and symmetric difference.

union()

All items that appear in either set, with no duplicates.

intersection()

Only the items that appear in both sets.

difference()

Items in the first set that do NOT appear in the second set.

symmetric_difference()

Items in either set, but not in both.

set_methods.py
python_devs = {"Alice", "Bob", "Charlie"}
js_devs = {"Bob", "Diana", "Eve"}

print("Union:", python_devs.union(js_devs))
print("Intersection:", python_devs.intersection(js_devs))
print("Difference:", python_devs.difference(js_devs))
print("Symmetric Difference:", python_devs.symmetric_difference(js_devs))
Output
Union: {'Alice', 'Bob', 'Charlie', 'Diana', 'Eve'}
Intersection: {'Bob'}
Difference: {'Alice', 'Charlie'}
Symmetric Difference: {'Alice', 'Charlie', 'Diana', 'Eve'}

Notice that difference() is not symmetric: python_devs.difference(js_devs) gives developers who only know Python, while js_devs.difference(python_devs) would give the reverse.

Operators vs Methods

Every set operation above also has a matching operator, which many Python developers prefer for its brevity.

OperationMethodOperator
Uniona.union(b)a | b
Intersectiona.intersection(b)a & b
Differencea.difference(b)a - b
Symmetric Differencea.symmetric_difference(b)a ^ b
set_operators.py
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}

print(a | b)   # union
print(a & b)   # intersection
print(a - b)   # difference
print(a ^ b)   # symmetric difference
Output
{1, 2, 3, 4, 5, 6}
{3, 4}
{1, 2}
{1, 2, 5, 6}
Which Should You Use?

Methods like union() and intersection() can accept any iterable (such as a list), while operators like | and & require both sides to be actual sets. Use methods for flexibility, operators for short, readable expressions between two sets.

Frozensets

A frozenset is an immutable version of a set — once created, you cannot add or remove items from it. Because frozensets never change, they can be used as dictionary keys or stored inside another set, which regular sets cannot do.

frozenset_example.py
readonly_colors = frozenset(["red", "green", "blue"])
print(readonly_colors)

try:
    readonly_colors.add("yellow")
except AttributeError as e:
    print("Error:", e)
Output
frozenset({'red', 'green', 'blue'})
Error: 'frozenset' object has no attribute 'add'

Deduplicating a List

One of the most common real-world uses of a set is removing duplicate values from a list. Converting a list to a set drops every duplicate instantly, and you can convert it back to a list afterward if order-independent uniqueness is all you need.

dedupe_list.py
emails = ["a@mail.com", "b@mail.com", "a@mail.com", "c@mail.com", "b@mail.com"]

unique_emails = list(set(emails))
print(unique_emails)
print("Total unique:", len(unique_emails))
Output
['b@mail.com', 'c@mail.com', 'a@mail.com']
Total unique: 3
Order Is Not Preserved

Converting a list to a set and back does not guarantee the original order. If order matters, use a different technique (such as dict.fromkeys(list_name)) instead.

Common Mistakes

Avoid These Mistakes
  • Writing {} expecting an empty set — it actually creates an empty dictionary.
  • Trying to access a set by index, like my_set[0] — sets are unordered and not subscriptable.
  • Using remove() on an item that might not exist, causing a KeyError; use discard() instead.
  • Assuming a set preserves the order items were added in.
  • Trying to put a mutable object like a list inside a set — set items must be hashable.

Best Practices

  • Use sets whenever you need uniqueness or fast membership checks.
  • Prefer discard() over remove() when the item's existence is uncertain.
  • Use frozenset when you need an immutable, hashable collection.
  • Use operators (| & - ^) for concise code between two sets, and methods when working with other iterables.
  • Convert a list to a set only when duplicate order does not matter.

Frequently Asked Questions

Can a set contain mixed data types?

Yes, as long as every item is hashable (immutable), a set can mix strings, numbers, and tuples, for example {1, "two", (3, 4)}.

Can I have a set of lists?

No. Lists are mutable and unhashable, so they cannot be stored inside a set. Use a tuple instead if you need a fixed sequence inside a set.

Are sets faster than lists?

For membership testing (in) and removing duplicates, yes — sets use hashing internally and are typically much faster than scanning a list.

How do I check if one set is a subset of another?

Use the subset operator or method: a.issubset(b) or a <= b returns True if every item in a is also in b.

Why did my printed set show items in a different order than I typed them?

Sets are unordered by design — Python organizes items internally for fast lookups, not to preserve insertion order.

Key Takeaways

  • A set stores unique, unordered items and is created with {} (non-empty) or set().
  • add(), remove(), discard(), and pop() modify a set's contents.
  • union, intersection, difference, and symmetric_difference combine sets, available as both methods and operators (| & - ^).
  • frozenset() creates an immutable set that can be used as a dictionary key.
  • Converting a list to a set is a quick way to remove duplicates.

Summary

Sets give you a fast, reliable way to store unique values and compare collections mathematically. Whether you need to deduplicate data, test membership quickly, or find what two collections have in common, sets are the right tool.

Next, you will learn about dictionaries — Python's key-value data structure for storing and looking up related information.

Lesson 17 Completed
  • You can create and modify sets.
  • You understand union, intersection, difference, and symmetric_difference.
  • You know the difference between set methods and operators.
  • You are ready to learn about dictionaries.
Next Lesson →

Dictionaries