Sets in Python
A set (set) in Python solves two specific tasks: fast membership testing (is an element in the collection?) and storing only unique values without duplicates. It's an unordered collection based on the mathematical concept of a set.
What is a set?
A set in Python is an unordered collection of unique elements. Two key properties of sets are:
- Unordered: elements have no specific order and are not indexed
- Unique: each element appears only once
Main characteristics of sets:
- Mutability: you can add and remove elements
- Immutable elements: only immutable objects can go inside a set (numbers, strings, tuples)
- Efficiency: optimized for fast membership testing
Because sets are based on the mathematical concept, they support union, intersection, and difference operations.
Creating sets
Using curly braces
Python 3.13# Set of integers numbers = {1, 2, 3, 4, 5} print(numbers){1, 2, 3, 4, 5}# Automatic duplicate removal duplicates = {1, 2, 2, 3, 3, 3, 4, 5, 5} print(duplicates){1, 2, 3, 4, 5}# Set with different data types mixed = {1, "hello", (1, 2, 3)} print(mixed){1, 'hello', (1, 2, 3)}
Important: You cannot create an empty set using {}, as this will create an empty dictionary. To create an empty set, use set().
Using the set() constructor
Python 3.13# Empty set empty_set = set() print(empty_set)set()# Creating a set from a list numbers_set = set([1, 2, 2, 3, 4, 4, 5]) print(numbers_set){1, 2, 3, 4, 5}# Creating a set from a string letters = set("hello") print(letters) # 'l' appears only once{'h', 'e', 'l', 'o'}
Basic operations with sets
Checking for element presence
Python 3.13fruits = {"apple", "banana", "cherry"} print("apple" in fruits)Trueprint("pear" in fruits)False
Adding and removing elements
Python 3.13fruits = {"apple", "banana"} # Adding a single element fruits.add("cherry") print(fruits){'apple', 'cherry', 'banana'}# Adding multiple elements fruits.update(["pear", "orange"]) print(fruits){'apple', 'cherry', 'banana', 'pear', 'orange'}# Removing an element fruits.remove("banana") # raises KeyError if element doesn't exist print(fruits){'apple', 'cherry', 'pear', 'orange'}# Safely removing an element fruits.discard("cherry") # doesn't raise an error if element doesn't exist print(fruits){'apple', 'pear', 'orange'}# Removing and returning an arbitrary element random_fruit = fruits.pop() print(random_fruit)appleprint(fruits){'pear', 'orange'}# Clearing the set fruits.clear() print(fruits)set()
Iterating through a set
Python 3.13colors = {"red", "blue", "green"} for color in colors: print(color)red blue green# The order of elements is not guaranteed!
Mathematical set operations
Three main operations: union, intersection, and difference. They're easy to visualise with Venn diagrams:

Union
All elements from both sets:
Python 3.13a = {1, 2, 3} b = {3, 4, 5} union_set = a | b print(union_set){1, 2, 3, 4, 5}
The same can be written as a.union(b).
Intersection
Elements that are in both sets:
Python 3.13a = {1, 2, 3, 4} b = {3, 4, 5, 6} intersection_set = a & b print(intersection_set){3, 4}
The same can be written as a.intersection(b).
Difference
Elements from the first set that are not in the second:
Python 3.13a = {1, 2, 3, 4} b = {3, 4, 5, 6} difference_set = a - b print(difference_set){1, 2}
The same can be written as a.difference(b).
Comparing sets
Python 3.13a = {1, 2, 3} b = {1, 2, 3, 4, 5} c = {1, 2, 3} # Set equality print(a == c) # Contains the same elementsTrue# Subsets print(a.issubset(b)) # All elements of a are in bTrueprint(a < b) # a is a proper subset of bTrue# Supersets print(b.issuperset(a)) # b contains all elements of aTrueprint(b > a) # b is a proper superset of aTrue# Checking for no common elements d = {6, 7, 8} print(a.isdisjoint(d)) # No common elementsTrue
Immutable sets (frozenset)
If you need an immutable version of a set, use frozenset:
Python 3.13# Creating a frozenset immutable_set = frozenset([1, 2, 3, 4]) print(immutable_set)frozenset({1, 2, 3, 4})# Attempting to modify a frozenset raises an error try: immutable_set.add(5) except AttributeError as e: print(f"Error: {e}")Error: 'frozenset' object has no attribute 'add'# frozenset can be used as a dictionary key or an element of another set normal_set = {frozenset([1, 2]), frozenset([3, 4])} print(normal_set){frozenset({1, 2}), frozenset({3, 4})}
Practical examples of using sets
1. Removing duplicates from a list
Python 3.13numbers = [1, 2, 2, 3, 3, 3, 4, 5, 5] unique_numbers = list(set(numbers)) print(unique_numbers)[1, 2, 3, 4, 5]
2. Finding common elements
Python 3.13users_group1 = ["Anna", "Ivan", "Maria", "Peter", "Elena"] users_group2 = ["Ivan", "Olga", "Elena", "Alex"] # Common elements (intersection) common_users = set(users_group1) & set(users_group2) print(f"Users in both groups: {common_users}")Users in both groups: {'Elena', 'Ivan'}# Elements only in the first group (difference) only_group1 = set(users_group1) - set(users_group2) print(f"Only in group 1: {only_group1}")Only in group 1: {'Maria', 'Anna', 'Peter'}# All unique elements (union) all_users = set(users_group1) | set(users_group2) print(f"All unique users: {all_users}")All unique users: {'Elena', 'Ivan', 'Maria', 'Anna', 'Olga', 'Alex', 'Peter'}
3. Checking for uniqueness of elements
Python 3.13def are_all_unique(items): """Checks if all elements in a sequence are unique.""" return len(set(items)) == len(items) print(are_all_unique([1, 2, 3, 4, 5]))Trueprint(are_all_unique([1, 2, 3, 3, 4]))False
Limitations and performance
Limitations
Set elements must be hashable (immutable):
Python 3.13# Works with immutable data types valid_set = {1, "hello", (1, 2, 3)} print(valid_set){1, 'hello', (1, 2, 3)}# Error with mutable data types try: invalid_set = {1, [2, 3], {"a": 1}} except TypeError as e: print(f"Error: {e}")Error: unhashable type: 'list'
You can add:
- Numbers (int, float, complex)
- Strings (str)
- Tuples (tuple) with hashable elements
- Frozenset
You cannot add:
- Lists (list)
- Dictionaries (dict)
- Sets (set)
Performance
Sets are optimized for fast operations:
Python 3.13import time # Speed comparison (demonstration) data = list(range(10000)) data_set = set(data) # Search in list vs. search in set start = time.time() 9999 in data # Slow: O(n) list_time = time.time() - start start = time.time() 9999 in data_set # Fast: O(1) set_time = time.time() - start print(f"Search in list: {list_time:.6f} sec") print(f"Search in set: {set_time:.6f} sec") print(f"Set is {list_time/set_time:.1f} times faster")Search in list: 0.000248 sec Search in set: 0.000003 sec Set is 82.7 times faster
Operations with O(1) complexity (constant time):
- Testing for membership: x in set
- Adding an element: set.add(x)
- Removing an element: set.remove(x), set.discard(x)
