Python sets are collections designed for unique values and fast membership tests. They are useful when you need to remove duplicates, compare groups, find common items, identify differences, or determine whether a value belongs to a collection.
A set is unordered, mutable, and cannot contain duplicate elements. Python also provides frozenset, an immutable version. This guide covers set creation, methods, mathematical operations, comprehensions, performance, nested structures, practical examples, and common mistakes.
For context, review lists, tuples, sets, and dictionaries, loops, and booleans.
What Is a Set?
A set stores each hashable value only once:
languages = {"Python", "JavaScript", "Python", "Go"}
print(languages)The duplicate "Python" is removed automatically. Do not depend on the display order because sets do not preserve a positional sequence like lists.
The official Python set documentation describes all operations. The data structures tutorial provides introductory examples.
Create a Set
numbers = {1, 2, 3}
letters = set(["a", "b", "a"])
characters = set("hello")Use set() for an empty set:
empty_set = set()Writing {} creates an empty dictionary, not a set.
Remove Duplicates
names = ["Ana", "Leo", "Ana", "Mia", "Leo"]
unique_names = set(names)
print(unique_names)This is concise, but the original order is not guaranteed. When order matters, use another technique:
unique_in_order = list(dict.fromkeys(names))Select the solution based on the actual requirement instead of assuming every deduplication task is the same.
Add Elements
permissions = {"read", "write"}
permissions.add("delete")
print(permissions)add() inserts one item. Adding an existing item does nothing and does not raise an error.
Add Several Elements
permissions.update(["share", "archive"])
permissions.update({"export", "print"})update() accepts any iterable and adds its elements individually.
Remove Elements
roles = {"admin", "editor", "viewer"}
roles.remove("viewer")remove() raises KeyError when the item does not exist. Use discard() when absence is acceptable:
roles.discard("guest")pop() removes and returns an arbitrary item. clear() removes everything.
Test Membership
blocked_users = {17, 23, 91}
user_id = 23
if user_id in blocked_users:
print("Access denied")Membership tests are one of the strongest reasons to use a set. They are generally efficient because sets use hashing. The Python in operator guide compares membership across strings, lists, sets, and dictionaries.
Union: Combine Unique Items
team_a = {"Ana", "Ben", "Chris"}
team_b = {"Chris", "Dana", "Eli"}
all_members = team_a | team_b
# Equivalent: team_a.union(team_b)The union contains every member that appears in either set.
Intersection: Find Common Items
common_members = team_a & team_b
# Equivalent: team_a.intersection(team_b)The result contains only values present in both sets.
Difference: Find Items in One Set Only
only_in_a = team_a - team_b
only_in_b = team_b - team_aDifference is directional. Switching the operands changes the result.
Symmetric Difference
exclusive_members = team_a ^ team_b
# Equivalent: team_a.symmetric_difference(team_b)The symmetric difference contains items that belong to one set but not both.
Subset and Superset Tests
required = {"read", "write"}
user_permissions = {"read", "write", "delete"}
print(required <= user_permissions)
print(user_permissions >= required)Use < and > for proper subset and proper superset tests, where the sets must not be equal.
Disjoint Sets
weekdays = {"Mon", "Tue", "Wed", "Thu", "Fri"}
weekend = {"Sat", "Sun"}
print(weekdays.isdisjoint(weekend))isdisjoint() returns true when the sets have no common elements.
Set Comprehensions
numbers = [1, 2, 2, 3, 4, 4, 5]
even_squares = {number ** 2 for number in numbers if number % 2 == 0}
print(even_squares)A set comprehension combines transformation, filtering, and automatic deduplication. Keep it simple enough to read.
What Can a Set Contain?
Set elements must be hashable. Common valid elements include numbers, strings, and tuples containing hashable values:
coordinates = {(10, 20), (30, 40)}Lists, dictionaries, and ordinary sets cannot be elements because they are mutable and unhashable:
# invalid = {[1, 2], [3, 4]}Use tuples or frozenset when an immutable representation fits the problem.
frozenset: An Immutable Set
required_permissions = frozenset({"read", "write"})A frozenset supports non-mutating set operations but has no add() or remove(). Because it is hashable, it can be used as a dictionary key or as an element of another set.
Compare Two Lists
old_users = [1, 2, 3, 4]
new_users = [2, 3, 4, 5, 6]
old_set = set(old_users)
new_set = set(new_users)
added = new_set - old_set
removed = old_set - new_set
unchanged = old_set & new_set
print(f"Added: {added}")
print(f"Removed: {removed}")
print(f"Unchanged: {unchanged}")This pattern is useful for synchronization, inventory checks, permission changes, and data reconciliation.
Find Common Words
text_a = "python makes automation readable"
text_b = "automation with python saves time"
words_a = set(text_a.lower().split())
words_b = set(text_b.lower().split())
common = words_a & words_b
print(common)Real text processing may require punctuation removal and normalization. The regex guide covers more advanced cleanup.
Validate Required Fields
required_fields = {"name", "email", "age"}
received_data = {"name": "Noah", "email": "[email protected]"}
missing_fields = required_fields - received_data.keys()
if missing_fields:
print(f"Missing fields: {sorted(missing_fields)}")A dictionary’s keys view supports set-like operations, making validation concise.
Count Unique Values
categories = ["book", "game", "book", "music", "game"]
unique_count = len(set(categories))
print(unique_count)If you also need frequencies, use collections.Counter instead of a set.
Sets and Performance
Sets are usually a good choice for repeated membership checks. Compare these intentions:
allowed_ids_list = [10, 20, 30, 40]
allowed_ids_set = {10, 20, 30, 40}
print(30 in allowed_ids_list)
print(30 in allowed_ids_set)Both are correct, but the set communicates that membership is the main operation. Do not convert a collection to a set repeatedly inside a loop; create the set once and reuse it.
Iterate over a Set
tags = {"python", "automation", "data"}
for tag in sorted(tags):
print(tag)Sort only when deterministic presentation is required. Sorting returns a list and adds work, so it should not be treated as a property of the set itself.
Copy a Set
original = {1, 2, 3}
copy_of_original = original.copy()
copy_of_original.add(4)
print(original)
print(copy_of_original)Assignment alone would create another reference to the same mutable set.
Update Operations in Place
values = {1, 2, 3}
values |= {3, 4}
values &= {2, 3, 4}
values -= {2}
values ^= {3, 5}These operators mutate the original set. Use named methods or intermediate variables when the compact syntax would make the code difficult to follow.
Common Mistakes
- Using
{}when an empty set is intended. - Expecting a stable positional order.
- Trying to access a set by index.
- Adding a list or dictionary as an element.
- Using
remove()when absence is normal. - Converting to a set when original order and duplicates matter.
- Rebuilding the same set inside a loop.
- Assuming difference is symmetric.
Practical Project: Compare Inventory Snapshots
def compare_inventory(
previous: list[str],
current: list[str],
) -> dict[str, set[str]]:
previous_set = set(previous)
current_set = set(current)
return {
"added": current_set - previous_set,
"removed": previous_set - current_set,
"unchanged": previous_set & current_set,
}
result = compare_inventory(
["A100", "B200", "C300"],
["B200", "C300", "D400"],
)
for category, items in result.items():
print(f"{category}: {sorted(items)}")The function clearly expresses the three relationships and can be tested independently with Pytest.
Frequently Asked Questions
Does a set preserve order?
Do not rely on positional order. Use a list when sequence order is part of the data model.
Can a set contain duplicates?
No. Equal hashable values appear only once.
When should I use a set instead of a list?
Use a set when uniqueness, membership checks, or set algebra are central. Use a list when order, indexes, and duplicates matter.
What is the difference between remove and discard?
remove() raises KeyError for a missing value. discard() does nothing.
What is frozenset used for?
It represents an immutable set and can be used where a hashable object is required.
Conclusion
Python sets make uniqueness and group comparison straightforward. Use them to remove duplicates, test membership, calculate unions and intersections, find added or removed values, and validate required fields.
Choose sets when order and duplicate counts are not part of the requirement. When those details matter, keep a list or another appropriate structure and use a set only as a temporary comparison tool.






