Understanding Sets and Frozen Sets in Python
Course: Python Training
Topic: Understanding Sets and Frozen Sets
Course Link: Python Training Course
Demo Registration: Register for a Course Demo
JustAcademy Website: Visit JustAcademy
1. Introduction to Sets in Python
A set is a built-in Python data structure used to store a collection of unique elements. Sets are useful when you need to remove duplicate values, check whether an item exists in a collection, or perform mathematical operations such as union, intersection, and difference.
Unlike lists and tuples, sets do not maintain positional indexes. Their elements are unordered, so you should not rely on a particular display or iteration order.
numbers = {10, 20, 30, 40, 50}
print(numbers)
Possible output:
{10, 20, 30, 40, 50}
The order shown in a set's output is not guaranteed. Sets automatically eliminate duplicate elements.
numbers = {10, 20, 10, 30, 20, 40}
print(numbers)
Possible output:
{40, 10, 20, 30}
The output contains only the distinct values. The order may differ when you run the program.
2. Learning Objectives
- Understand Python sets and their main characteristics.
- Create sets using curly braces and the
set() constructor.
- Understand uniqueness, unordered elements, and hashable values.
- Add and remove elements from a set.
- Perform union, intersection, difference, and symmetric difference operations.
- Use comparison operators to check subset and superset relationships.
- Understand frozen sets and their immutable nature.
- Compare sets and frozen sets.
- Apply sets to duplicate removal, data comparison, and membership testing.
3. Characteristics of Sets
| Characteristic |
Explanation |
| Unique elements |
A set stores only one occurrence of each distinct element. |
| Unordered |
Elements do not have fixed positional indexes or guaranteed insertion order. |
| Mutable |
A normal set can be changed by adding or removing elements. |
| No indexing or slicing |
Set elements cannot be accessed with expressions such as items[0]. |
| Hashable elements |
Elements must be hashable, such as strings, integers, and suitable tuples. |
| Mathematical operations |
Sets support union, intersection, difference, and related operations. |
| Membership testing |
The in operator can check whether an element exists in a set. |
4. Creating Sets in Python
4.1 Creating a Set Using Curly Braces
You can create a non-empty set by placing comma-separated elements inside curly braces.
fruits = {"Apple", "Banana", "Mango", "Orange"}
print(fruits)
print(type(fruits))
Possible output:
{'Apple', 'Banana', 'Mango', 'Orange'}
<class 'set'>
The exact order of the displayed elements is not guaranteed.
4.2 Creating an Empty Set
To create an empty set, use set(). Empty curly braces create an empty dictionary, not an empty set.
empty_set = set()
empty_dictionary = {}
print(type(empty_set))
print(type(empty_dictionary))
Output:
<class 'set'>
<class 'dict'>
4.3 Creating a Set from a List
The set() constructor can convert an iterable, such as a list, into a set. Duplicate values are removed.
numbers = [1, 2, 2, 3, 4, 4, 5]
unique_numbers = set(numbers)
print(unique_numbers)
Possible output:
{1, 2, 3, 4, 5}
4.4 Creating a Set from a String
When a string is passed to set(), Python creates a set containing its distinct characters. Spaces are treated as characters too.
letters = set("banana")
print(letters)
Possible output:
{'b', 'a', 'n'}
Repeated characters are stored only once.
5. Understanding Set Elements and Hashability
Set elements must be hashable. Common hashable values include strings, integers, floating-point numbers, Boolean values, and tuples whose elements are all hashable.
valid_set = {
10,
"Python",
3.14,
(1, 2, 3)
}
print(valid_set)
Lists, dictionaries, and ordinary sets cannot be added as elements because they are unhashable.
# This raises TypeError because a list is unhashable.
items = {[1, 2], [3, 4]}
If you need to represent a collection of collections as set elements, you can use tuples when their contents are hashable or use frozen sets for set-like collections.
5.1 Numerically Equal Values
Values that compare equal can be treated as the same set element. For example, 1 and 1.0 compare equal in Python, so they do not create two distinct entries in a set.
values = {1, 1.0, 2}
print(values)
print(len(values))
Possible output:
{1, 2}
2
6. Adding Elements to a Set
6.1 The add() Method
The add() method inserts one element into a set. If the element already exists, the set remains unchanged.
languages = {"Python", "Java"}
languages.add("JavaScript")
print(languages)
Possible output:
{'Python', 'Java', 'JavaScript'}
6.2 Adding a Duplicate Element
numbers = {10, 20, 30}
numbers.add(20)
print(numbers)
print(len(numbers))
Possible output:
{10, 20, 30}
3
The duplicate value is not added again, so the number of elements stays the same.
6.3 The update() Method
The update() method adds elements from one or more iterables to an existing set.
numbers = {1, 2, 3}
numbers.update([3, 4, 5])
numbers.update((5, 6, 7))
print(numbers)
Output:
{1, 2, 3, 4, 5, 6, 7}
Unlike add(), which inserts one element, update() processes the elements in an iterable.
7. Removing Elements from a Set
7.1 The remove() Method
The remove() method deletes a specified element. If the element is not present, Python raises a KeyError.
fruits = {"Apple", "Banana", "Mango"}
fruits.remove("Banana")
print(fruits)
Possible output:
{'Apple', 'Mango'}
7.2 The discard() Method
The discard() method removes an element if it exists. If the element is absent, it does not raise an error.
fruits = {"Apple", "Banana", "Mango"}
fruits.discard("Banana")
fruits.discard("Orange")
print(fruits)
Possible output:
{'Apple', 'Mango'}
7.3 The pop() Method
The pop() method removes and returns an arbitrary element from a set. Because sets are unordered, you should not expect it to remove a specific element.
numbers = {10, 20, 30}
removed_value = numbers.pop()
print("Removed:", removed_value)
print("Remaining:", numbers)
The removed element can vary. Do not rely on a specific value being returned.
7.4 The clear() Method
The clear() method removes all elements from a set.
numbers = {10, 20, 30}
numbers.clear()
print(numbers)
Output:
set()
7.5 Comparing Removal Methods
| Method |
Behavior |
If the element is missing |
remove(x) |
Removes the specified element. |
Raises KeyError. |
discard(x) |
Removes the specified element if present. |
No error is raised. |
pop() |
Removes and returns an arbitrary element. |
Raises KeyError if the set is empty. |
clear() |
Removes every element. |
Leaves an empty set. |
8. Mathematical Operations on Sets
Python sets support several mathematical operations that are useful for comparing groups of data. Consider the following two sets:
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
8.1 Union
The union combines all unique elements from both sets. Use the | operator or the union() method.
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
print(A | B)
print(A.union(B))
Output:
{1, 2, 3, 4, 5, 6, 7, 8}
{1, 2, 3, 4, 5, 6, 7, 8}
8.2 Intersection
The intersection returns only the elements shared by both sets. Use the & operator or the intersection() method.
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
print(A & B)
print(A.intersection(B))
Output:
{4, 5}
{4, 5}
8.3 Difference
The difference returns elements that belong to the first set but not the second. Use the - operator or the difference() method.
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
print(A - B)
print(B - A)
Output:
{1, 2, 3}
{6, 7, 8}
Difference is directional: A - B and B - A may produce different results.
8.4 Symmetric Difference
The symmetric difference returns elements that appear in either set but not in both. Use the ^ operator or the symmetric_difference() method.
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
print(A ^ B)
print(A.symmetric_difference(B))
Output:
{1, 2, 3, 6, 7, 8}
{1, 2, 3, 6, 7, 8}
8.5 Set Operation Summary
| Operation |
Operator |
Method |
Meaning |
| Union |
A | B |
A.union(B) |
All distinct elements from both sets. |
| Intersection |
A & B |
A.intersection(B) |
Elements common to both sets. |
| Difference |
A - B |
A.difference(B) |
Elements in A but not in B. |
| Symmetric difference |
A ^ B |
A.symmetric_difference(B) |
Elements in either set but not both. |
9. Comparing Sets
9.1 Subset
A set A is a subset of set B if every element of A is also present in B. Use issubset() or the <= operator.
A = {1, 2}
B = {1, 2, 3, 4}
print(A.issubset(B))
print(A <= B)
Output:
True
True
9.2 Proper Subset
A is a proper subset of B if all elements of A belong to B and A is not equal to B. Use the < operator.
A = {1, 2}
B = {1, 2, 3}
print(A < B)
Output:
True
9.3 Superset
A set A is a superset of B if A contains every element of B. Use issuperset() or the >= operator.
A = {1, 2, 3, 4}
B = {1, 2}
print(A.issuperset(B))
print(A >= B)
Output:
True
True
9.4 Disjoint Sets
Two sets are disjoint if they have no elements in common. Use the isdisjoint() method.
A = {1, 2, 3}
B = {4, 5, 6}
C = {3, 4, 5}
print(A.isdisjoint(B))
print(A.isdisjoint(C))
Output:
True
False
10. Other Useful Set Operations
10.1 Membership Testing
The in and not in operators check whether an element belongs to a set.
courses = {"Python", "SQL", "Power BI"}
print("Python" in courses)
print("Java" not in courses)
Output:
True
True
10.2 Finding the Number of Elements
The len() function returns the number of unique elements in a set.
numbers = {10, 20, 20, 30, 40}
print(len(numbers))
Output:
4
10.3 Iterating Through a Set
You can use a for loop to process every element. The order of iteration is not guaranteed.
languages = {"Python", "Java", "JavaScript"}
for language in languages:
print(language)
The program prints all three languages, but their order may vary.
10.4 Creating a Sorted View of a Set
Although a set itself is unordered, the sorted() function returns a sorted list containing its elements.
numbers = {40, 10, 30, 20}
sorted_numbers = sorted(numbers)
print(sorted_numbers)
print(type(sorted_numbers))
Output:
[10, 20, 30, 40]
<class 'list'>
The original object remains a set. The result of sorted() is a list.
11. Set Methods That Modify Another Set
Some set methods update the original set instead of returning a separate result.
| Method |
Effect on the original set |
update(other) |
Adds elements from other iterables. |
intersection_update(other) |
Keeps only elements also present in the other set or sets. |
difference_update(other) |
Removes elements found in the other set or sets. |
symmetric_difference_update(other) |
Keeps elements found in either set but not both. |
11.1 Example of intersection_update()
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
A.intersection_update(B)
print(A)
Output:
{3, 4}
11.2 Example of difference_update()
A = {1, 2, 3, 4}
B = {3, 4}
A.difference_update(B)
print(A)
Output:
{1, 2}
12. Introduction to Frozen Sets
A frozen set, created with the frozenset() constructor, is an immutable version of a set. Once a frozen set has been created, its elements cannot be added or removed.
Frozen sets support set operations such as union, intersection, and difference. They are also hashable when their elements satisfy the required hashability rules, which allows a frozen set to be used as an element of another set or as a dictionary key.
numbers = frozenset([10, 20, 30, 20])
print(numbers)
print(type(numbers))
Possible output:
frozenset({10, 20, 30})
<class 'frozenset'>
The duplicate value is removed, just as it is with a regular set.
13. Creating Frozen Sets
13.1 Creating a Frozen Set from a List
numbers = [1, 2, 3, 3, 4]
frozen_numbers = frozenset(numbers)
print(frozen_numbers)
Possible output:
frozenset({1, 2, 3, 4})
13.2 Creating a Frozen Set from a String
letters = frozenset("programming")
print(letters)
The resulting frozen set contains each distinct character once. Its display order is not guaranteed.
13.3 Creating an Empty Frozen Set
empty_frozen = frozenset()
print(empty_frozen)
print(type(empty_frozen))
Output:
frozenset()
<class 'frozenset'>
14. Understanding Frozen Set Immutability
Frozen sets cannot be changed after creation. Methods such as add(), remove(), and clear() are not available for modifying their contents.
frozen_numbers = frozenset([1, 2, 3])
# This raises AttributeError:
frozen_numbers.add(4)
To produce a changed collection, perform a set operation or create a new frozen set.
frozen_numbers = frozenset([1, 2, 3])
new_numbers = frozen_numbers.union([4, 5])
print(frozen_numbers)
print(new_numbers)
print(type(new_numbers))
Output:
frozenset({1, 2, 3})
frozenset({1, 2, 3, 4, 5})
<class 'frozenset'>
The original frozen set remains unchanged. Operations between frozen sets return a frozen set; when mixed with a mutable set, the result type of a binary operation follows the first operand.
15. Set vs. Frozen Set
| Feature |
set |
frozenset |
| Mutability |
Mutable |
Immutable |
| Adding elements |
Supports add() and update(). |
Cannot add elements after creation. |
| Removing elements |
Supports remove(), discard(), and other modifying methods. |
Cannot remove elements after creation. |
| Duplicates |
Not allowed. |
Not allowed. |
| Ordering |
Unordered. |
Unordered. |
| Set operations |
Supported. |
Supported. |
| Hashable |
No. |
Yes, when its elements are hashable. |
| Can be a dictionary key |
No. |
Yes, if hashable. |
| Can be an element of another set |
No. |
Yes, if hashable. |
| Typical use |
Collections that may change. |
Collections that must remain immutable. |
16. Using Frozen Sets as Dictionary Keys
Because a frozen set is immutable and hashable when its elements are hashable, it can be used as a dictionary key. A normal set cannot be used as a dictionary key because it is mutable and unhashable.
permissions = {
frozenset({"read", "write"}): "Editor",
frozenset({"read"}): "Viewer"
}
print(permissions[frozenset({"read"})])
print(permissions[frozenset({"write", "read"})])
Output:
Viewer
Editor
Set equality does not depend on element order, so frozen sets containing the same elements can be used to look up the same dictionary entry.
17. Using Frozen Sets Inside Sets
A frozen set can be an element of another set because it is hashable when its elements are hashable. A regular set cannot be stored inside another set.
group_a = frozenset([1, 2])
group_b = frozenset([3, 4])
collection = {group_a, group_b}
print(collection)
Possible output:
{frozenset({1, 2}), frozenset({3, 4})}
This is useful when you need to store distinct groups of elements in a larger collection.
18. Practical Applications of Sets
18.1 Removing Duplicates from a List
Sets provide a simple way to eliminate duplicate values from a list.
names = ["Amit", "Priya", "Amit", "Rahul", "Priya"]
unique_names = set(names)
print(unique_names)
Possible output:
{'Amit', 'Priya', 'Rahul'}
If you need to preserve the original order of first occurrences, use dict.fromkeys() instead of converting the list directly to a set.
names = ["Amit", "Priya", "Amit", "Rahul", "Priya"]
unique_names = list(dict.fromkeys(names))
print(unique_names)
Output:
['Amit', 'Priya', 'Rahul']
18.2 Finding Common Students
Suppose two courses have different student enrollment lists. Intersection can identify students enrolled in both courses.
python_students = {"Amit", "Priya", "Rahul", "Neha"}
sql_students = {"Priya", "Neha", "Karan", "Vikram"}
common_students = python_students & sql_students
print(common_students)
Possible output:
{'Priya', 'Neha'}
18.3 Finding Students Enrolled in Only One Course
python_students = {"Amit", "Priya", "Rahul"}
sql_students = {"Priya", "Neha", "Karan"}
only_one_course = python_students ^ sql_students
print(only_one_course)
Possible output:
{'Amit', 'Rahul', 'Neha', 'Karan'}
The symmetric difference finds students who appear in exactly one of the two sets.
18.4 Checking Required Skills
Sets can compare the skills a candidate has with the skills required for a job.
candidate_skills = {"Python", "SQL", "Excel", "Power BI"}
required_skills = {"Python", "SQL", "Power BI"}
missing_skills = required_skills - candidate_skills
if not missing_skills:
print("Candidate has all required skills.")
else:
print("Missing skills:", missing_skills)
Output:
Candidate has all required skills.
18.5 Keeping Configuration Options Immutable
A frozen set can represent a collection of options that should not be changed after creation.
allowed_roles = frozenset({"admin", "editor", "viewer"})
user_role = "editor"
if user_role in allowed_roles:
print("Role is allowed.")
else:
print("Role is not allowed.")
Output:
Role is allowed.
This pattern can help express immutable collections of allowed values. It does not replace full authentication or authorization controls.
19. Common Mistakes and Troubleshooting
| Mistake |
Reason |
Solution |
Using {} for an empty set |
Empty curly braces create a dictionary. |
Use set(). |
| Trying to access a set by index |
Sets do not support indexing. |
Use iteration or convert to a list if positional access is required. |
| Expecting duplicate values to remain |
Sets store unique elements. |
Use a list if duplicates must be preserved. |
| Adding a list to a set |
Lists are unhashable. |
Use hashable values such as tuples when appropriate. |
Removing a missing value with remove() |
The element does not exist. |
Use discard() if missing values are expected. |
| Expecting a frozen set to change |
Frozen sets are immutable. |
Create a new frozen set from the desired elements. |
| Assuming a set has a fixed order |
Sets are unordered. |
Use sorted() when sorted output is required. |
| Trying to use a normal set as a dictionary key |
Mutable sets are unhashable. |
Use a frozen set when the set of elements must be a key. |
20. Best Practices for Sets and Frozen Sets
- Use sets when you need unique values and do not need positional ordering.
- Use
set() to create an empty set.
- Use
add() for one element and update() for multiple elements.
- Use
discard() when an element may be absent and you want to avoid a removal error.
- Use set operations to compare groups of values instead of writing unnecessary nested loops.
- Use
sorted() when deterministic, sorted output is needed.
- Use frozen sets for immutable collections that need to be hashable.
- Remember that elements of both sets and frozen sets must be hashable.
- Do not depend on the order in which set elements are displayed or iterated.
- Choose lists or tuples instead when position and order are important to the application.
21. Practice Exercises
Exercise 1: Remove Duplicate Numbers
Convert a list containing repeated numbers into a set and print the unique values.
numbers = [1, 2, 2, 3, 4, 4, 5, 5]
unique_numbers = set(numbers)
print(unique_numbers)
Expected result: The set contains 1, 2, 3, 4, 5, with no duplicates. The display order is not guaranteed.
Exercise 2: Perform Set Operations
Given two sets, print their union, intersection, difference, and symmetric difference.
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}
print("Union:", A | B)
print("Intersection:", A & B)
print("Difference:", A - B)
print("Symmetric difference:", A ^ B)
Expected results:
Union: {1, 2, 3, 4, 5, 6}
Intersection: {3, 4}
Difference: {1, 2}
Symmetric difference: {1, 2, 5, 6}
The order of elements in each displayed set is not guaranteed.
Exercise 3: Create a Frozen Set
Create a frozen set of programming languages and display its type.
languages = frozenset(["Python", "Java", "SQL"])
print(languages)
print(type(languages))
Expected result: A frozen set containing the three distinct languages, followed by <class 'frozenset'>.
Exercise 4: Compare Course Enrollment
Find students enrolled in both Python and SQL courses and those enrolled in Python but not SQL.
python_students = {"Amit", "Priya", "Rahul", "Neha"}
sql_students = {"Priya", "Neha", "Karan"}
print("Both courses:", python_students & sql_students)
print("Python only:", python_students - sql_students)
Expected results:
Both courses: {'Priya', 'Neha'}
Python only: {'Amit', 'Rahul'}
Exercise 5: Use a Frozen Set as a Dictionary Key
Create a dictionary that maps frozen sets of permissions to role names.
roles = {
frozenset({"read"}): "Viewer",
frozenset({"read", "write"}): "Editor"
}
requested_permissions = frozenset({"read"})
print(roles[requested_permissions])
Expected output:
Viewer
22. Interview Questions and Answers
Q1. What is a set in Python?
A set is an unordered collection of unique, hashable elements. It is commonly used for duplicate removal, membership testing, and mathematical set operations.
Q2. How do you create an empty set?
Use set(). The expression {} creates an empty dictionary.
Q3. What is the difference between a list and a set?
A list preserves element order, supports indexing, and allows duplicates. A set stores unique elements and does not support indexing or slicing.
Q4. What is the difference between add() and update()?
add() inserts one element. update() inserts elements from one or more iterables.
Q5. What is the difference between remove() and discard()?
remove() raises a KeyError if the element is absent. discard() does not raise an error when the element is missing.
Q6. What is a frozen set?
A frozen set is an immutable version of a set. Its contents cannot be changed after creation.
Q7. Can a frozen set be used as a dictionary key?
Yes. A frozen set is hashable when its elements are hashable, so it can be used as a dictionary key.
Q8. What is the difference between union and intersection?
Union combines all distinct elements from both sets. Intersection returns only the elements common to both sets.
Q9. What is symmetric difference?
Symmetric difference returns elements that belong to either set but not to both.
Q10. Can a set contain a list?
No. Lists are unhashable. A set can contain suitable tuples or frozen sets when their elements satisfy hashability requirements.
Q11. Are sets ordered in Python?
No. Sets do not guarantee element order and do not support indexing or slicing.
Q12. Can you modify a frozen set after creation?
No. You can create a new frozen set using a set operation or by constructing one from a different collection.
23. Quick Revision Checklist
- A set stores unique, hashable elements.
- Sets are unordered and do not support indexing or slicing.
- Use curly braces for non-empty sets and
set() for an empty set.
- Use
add() to insert one element and update() to insert several.
- Use
remove(), discard(), pop(), or clear() to remove elements.
- Use
| for union, & for intersection, - for difference, and ^ for symmetric difference.
- Use
issubset(), issuperset(), and isdisjoint() to compare sets.
- A frozen set is immutable and hashable when its elements are hashable.
- Frozen sets can be dictionary keys or elements of another set.
- Use
sorted() when you need ordered output from a set.
24. Conclusion
Sets and frozen sets are important Python data structures for handling unique collections of data. Sets are mutable and are ideal when elements need to be added or removed. Frozen sets provide an immutable alternative that can be used as a dictionary key or as an element of another set.
By practicing set creation, element management, mathematical operations, comparisons, and frozen-set usage, you can solve many common data-processing problems with concise and readable Python code.
Additional Learning Resources