A set in Python is a mutable collection used to store unique elements. Unlike a list, a set does not maintain elements as an index-based sequence, and duplicate values are automatically eliminated.
Sets are especially useful when a program needs fast average-case membership testing, duplicate removal, or mathematical operations such as union, intersection, difference, and symmetric difference.
Python also provides frozenset, an immutable version
of a set that can be used in situations where the set itself needs to be hashable.
Creating a Set in Python
A set can be created using curly braces with comma-separated values.
languages = {"Python", "JavaScript", "Java"}
print(languages)
Duplicate values are automatically removed.
numbers = {10, 20, 10, 30, 20}
print(numbers)
The resulting set contains each distinct value only once.
Creating an Empty Set
An important detail is that {} creates an empty dictionary,
not an empty set. Use set() to create an empty set.
empty_set = set()
empty_dictionary = {}
print(empty_set)
print(empty_dictionary)
Adding Elements to a Set
The add() method inserts one element into a set.
If the element already exists, the set remains unchanged.
skills = {"Python", "SQL"}
skills.add("Git")
skills.add("Python")
print(skills)
Adding Multiple Elements
The update() method adds elements from another
iterable to the set.
skills = {"Python", "SQL"}
skills.update(["Git", "Docker", "Python"])
print(skills)
Removing Elements from a Set
remove()
The remove() method removes a specified element.
It raises a KeyError if the element does not exist.
skills = {"Python", "SQL", "Git"}
skills.remove("SQL")
print(skills)
discard()
The discard() method also removes an element,
but it does not raise an exception when the element is missing.
skills = {"Python", "SQL", "Git"}
skills.discard("SQL")
skills.discard("Docker")
print(skills)
pop()
The pop() method removes and returns an arbitrary
element from the set. Since sets are not index-based sequences, you should not rely
on which element will be removed.
skills = {"Python", "SQL", "Git"}
removed = skills.pop()
print("Removed:", removed)
print("Remaining:", skills)
clear()
The clear() method removes all elements from the set.
skills = {"Python", "SQL", "Git"}
skills.clear()
print(skills)
Checking Membership in a Set
The in operator is one of the most useful operations
on a set. It checks whether a value exists in the collection.
skills = {"Python", "SQL", "Docker"}
print("Python" in skills)
print("Java" in skills)
Set membership testing is typically O(1) on average, making sets useful when the same membership check needs to be performed many times.
Finding the Size of a Set
Use the built-in len() function to find the number
of unique elements in a set.
numbers = {10, 20, 30, 40}
print(len(numbers))
Iterating Over a Set
A set can be traversed with a for loop.
Since a set is not an index-based sequence, iteration should not depend on a particular order.
skills = {"Python", "SQL", "Git"}
for skill in skills:
print(skill)
Set Union
The union of two sets contains every unique element found in either set.
You can use the | operator or the
union() method.
frontend = {"HTML", "CSS", "JavaScript"}
backend = {"Python", "JavaScript", "C#"}
all_skills = frontend | backend
print(all_skills)
The result contains JavaScript only once even though it appears in both sets.
Set Intersection
The intersection contains only elements that exist in both sets.
frontend = {"HTML", "CSS", "JavaScript"}
backend = {"Python", "JavaScript", "C#"}
common = frontend & backend
print(common)
The & operator performs set intersection.
The equivalent method is intersection().
Set Difference
The difference contains elements that exist in the first set but not in the second set.
frontend = {"HTML", "CSS", "JavaScript"}
backend = {"Python", "JavaScript", "C#"}
frontend_only = frontend - backend
print(frontend_only)
Difference is directional. A - B and
B - A can produce different results.
Symmetric Difference
The symmetric difference contains elements that belong to either set, but not to both.
team_a = {"Python", "JavaScript", "SQL"}
team_b = {"JavaScript", "C#", "Docker"}
different = team_a ^ team_b
print(different)
Set Relationship Checks
Python provides methods for determining relationships between sets, including subset, superset, and disjoint checks.
required = {"Python", "SQL"}
available = {"Python", "SQL", "Docker"}
print(required.issubset(available))
print(available.issuperset(required))
mobile = {"Swift", "Kotlin"}
print(required.isdisjoint(mobile))
Set Comprehension
A set comprehension provides a concise way to create a set from an iterable. Duplicate results are automatically removed.
numbers = [1, 2, 2, 3, 4, 4, 5]
squares = {
number * number
for number in numbers
}
print(squares)
Set comprehensions are useful when both transformation and uniqueness are required.
Removing Duplicates from a List
One of the most common uses of a Python set is removing duplicate values from a list.
numbers = [10, 20, 10, 30, 20, 40]
unique_numbers = list(set(numbers))
print(unique_numbers)
This approach removes duplicates, but the resulting order should not be relied upon. If preserving the original order is important, a different approach should be used.
Removing Duplicates While Preserving Order
A dictionary can be useful when unique values must retain their first-seen order.
Since modern Python dictionaries preserve insertion order, converting through
dict.fromkeys() is a concise solution.
numbers = [10, 20, 10, 30, 20, 40]
unique_numbers = list(dict.fromkeys(numbers))
print(unique_numbers)
Set with Different Data Types
A set can contain different hashable Python objects. Strings, numbers, and tuples containing hashable elements can be set members.
items = {
"Python",
100,
3.14,
(10, 20)
}
print(items)
Mutable objects such as lists and dictionaries cannot be directly stored as set elements because they are not hashable.
Set vs List
Lists and sets are both useful collections, but they are designed for different purposes.
| Feature | List | Set |
|---|---|---|
| Duplicates | Allowed | Not stored |
| Indexing | Supported | Not supported |
| Membership | O(n) typical | O(1) average |
| Ordering | Ordered | Not an index-based sequence |
| Primary use | Sequences | Uniqueness and membership |
frozenset in Python
A frozenset is an immutable set. Its elements
cannot be added or removed after creation.
permissions = frozenset({
"read",
"write"
})
print(permissions)
Because a frozenset is immutable and hashable when its elements are hashable, it can be used as a dictionary key or as an element of another set.
role_permissions = {
frozenset({"read", "write"}): "Editor",
frozenset({"read"}): "Viewer"
}
print(role_permissions[frozenset({"read", "write"})])
Set Time Complexity
Python sets are hash-table-based collections. Many common operations have O(1) average-case complexity.
| Operation | Average Complexity |
|---|---|
| Add | O(1) |
| Remove | O(1) |
| Membership check | O(1) |
| Length | O(1) |
| Iteration | O(n) |
Set union, intersection, and difference operations depend on the sizes of the sets involved. The exact cost can vary based on the operation and implementation.
Practical Example: Comparing Developer Skills
Sets are useful for comparing collections of unique values. For example, an application can determine which technologies are shared between two developers or which skills are unique to one developer.
developer_a = {
"Python",
"SQL",
"Docker",
"Git"
}
developer_b = {
"Python",
"JavaScript",
"Git",
"React"
}
common_skills = developer_a & developer_b
only_a = developer_a - developer_b
all_skills = developer_a | developer_b
print("Common:", common_skills)
print("Only A:", only_a)
print("All:", all_skills)
Common Set Mistakes in Python
- Using
{}when an empty set is required. Useset()instead. - Trying to access a set with an index such as
my_set[0]. - Assuming a particular iteration order for a set.
- Using
remove()when the element may not exist and an exception is not desired. - Assuming
pop()removes the first or last element. - Trying to add mutable objects such as lists or dictionaries directly to a set.
- Using a set when duplicate values or positional access are important.
- Converting a list to a set without considering whether the original order must be preserved.
When Should You Use a Set?
A set is a good choice when uniqueness or membership testing is more important than maintaining an index-based sequence.
- You need to store unique values.
- You frequently check whether a value exists.
- You need union, intersection, or difference operations.
- You want to eliminate duplicate values.
- You need to compare collections based on their members rather than positions.
Key Takeaways
- Python sets store unique elements.
- Sets do not provide normal index-based access.
- Use set() to create an empty set because {} creates an empty dictionary.
- add() inserts one element, while update() can add multiple elements.
- remove() raises an exception for a missing element, while discard() does not.
- Sets support union, intersection, difference, and symmetric difference operations.
- Set membership testing is typically O(1) on average.
- frozenset provides an immutable and hashable set-like collection.
- Sets are useful for duplicate removal, membership testing, and comparing collections.
- Use a list instead when ordering, duplicates, or index-based access are central to the problem.