A set in Python is an unordered collection of unique items. This Python set exercise aims to help you learn and practice set operations.
This article offers 30 Python set practice questions, organized by difficulty, to help you get comfortable with sets through hands-on exercises.
Starting with basics set operations and standard functions such as unions and intersections, these exercises progress to subset logic and efficient data updates. You’ll also explore advanced concepts like set comprehensions, membership testing, and frozensets. By the end, you’ll master using sets for deduplication and optimizing real-world programming.
Each coding challenge includes a Practice Problem, Hint, Solution code, and detailed Explanation, ensuring you don’t just copy code, but genuinely practice and understand how and why it works.
- All solutions have been fully tested on Python 3.
- Use our Online Code Editor to solve these exercises in real time.
Also Read:
- Python Sets
- Python Set Quiz: MCQs to help you get familiar with Python set.
+ Table of Contents (31 Exercises)
Table of contents
- Exercise 1: Basic Set Operations
- Exercise 2: Clear All Elements
- Exercise 3: Find the Length of a Set
- Exercise 4: Check if a Set is Empty
- Exercise 5: Union of Sets
- Exercise 6: Intersection of Sets
- Exercise 7: Difference of Sets
- Exercise 8: Symmetric Difference
- Exercise 9: Find Max and Min
- Exercise 10: Sum of Set Elements
- Exercise 11: Add a List of Elements
- Exercise 12: Update with Multiple Iterables
- Exercise 13: Check Subset and Superset
- Exercise 14: Intersection Check with isdisjoint()
- Exercise 15: Set Difference Update
- Exercise 16: Set Intersection Update
- Exercise 17: Set Symmetric Difference Update
- Exercise 18: Remove Items Simultaneously
- Exercise 19: The Pop Operation
- Exercise 20: Filter a Set
- Exercise 21: Find Common Elements in Lists
- Exercise 22: Count Unique Words
- Exercise 23: Convert Set to Joined String
- Exercise 24: Proper Subset and Superset
- Exercise 25: Frozen Set
- Exercise 26: Set Comprehension
- Exercise 27: Remove Duplicates (Preserving Order)
- Exercise 28: Multi-Set Difference
- Exercise 29: Set of Tuples
- Exercise 30: Shallow Copy vs. Assignment
- Exercise 31: Membership Testing Performance
Exercise 1: Basic Set Operations
Problem Statement: Write a Python program to create a set, add a new element to it, remove an element using remove(), and discard an element using discard().
Purpose: This exercise introduces you to the core mutation methods of Python sets. Understanding the difference between remove() and discard() is essential because one raises an error on missing elements while the other does not, making each suited to different real-world scenarios.
Given Input: fruits = {"apple", "banana", "cherry"}
Expected Output:
{'apple', 'banana', 'cherry', 'mango'}
after add,{'apple', 'cherry', 'mango'}
after remove,{'apple', 'cherry', 'mango'}
after discard (no error even if element is absent)
▼ Hint
- Use curly braces
{}orset()to create a set with initial values. - Use
.add(element)to insert a single new element into the set. - Use
.remove(element)to delete an element — it raises aKeyErrorif the element does not exist. - Use
.discard(element)to delete an element safely — it does nothing if the element is not found.
▼ Solution & Explanation
Solution:
Explanation:
{"apple", "banana", "cherry"}: Creates a set literal with three string elements. Sets are unordered and store only unique values..add("mango"): Inserts"mango"into the set. If the element already exists, the set remains unchanged..remove("banana"): Deletes"banana"from the set. If the element is absent, Python raises aKeyError, so use this only when you are certain the element exists..discard("grape"): Attempts to remove"grape", but since it is not in the set, the operation is silently ignored with no error raised. This makesdiscard()the safer choice for uncertain removals.
Exercise 2: Clear All Elements
Problem Statement: Write a Python program to remove all elements from a set using .clear(), while keeping the variable itself intact.
Purpose: This exercise shows the difference between emptying a set and deleting the variable entirely. Using .clear() is useful when you want to reuse the same set object later in your program without reassigning it.
Given Input: colors = {"red", "green", "blue"}
Expected Output: set()
▼ Hint
- Call
.clear()on the set variable to remove all its elements in place. - After clearing, the variable still exists and refers to an empty set, not
None. - An empty set is displayed as
set()in Python, not{}(which would represent an empty dictionary).
▼ Solution & Explanation
Solution:
Explanation:
colors.clear(): Removes every element from the set in place. The variablecolorscontinues to exist and now points to an empty set object.set()in output: Python prints an empty set asset()rather than{}to avoid ambiguity with an empty dictionary, which also uses curly braces.- Contrast with
del: Writingdel colorswould remove the variable entirely from memory, making any further reference to it raise aNameError..clear()keeps the variable alive but empties its contents.
Exercise 3: Find the Length of a Set
Problem Statement: Write a Python program to determine how many elements are in a set without using the built-in len() function.
Purpose: This exercise strengthens your understanding of iteration and manual counting logic. While len() is convenient, building a counter loop reinforces how Python traverses collections internally and prepares you for situations where custom counting logic is required.
Given Input: animals = {"cat", "dog", "bird", "fish"}
Expected Output: Length of set: 4
▼ Hint
- Initialize a counter variable to
0before the loop. - Use a
forloop to iterate over the set and increment the counter by1for each element. - After the loop, print the counter value as the length.
▼ Solution & Explanation
Solution:
Explanation:
count = 0: Initializes the counter to zero before iteration begins, ensuring an accurate tally from the start.for _ in animals: Iterates over every element in the set. The underscore_is a conventional placeholder variable name used when the element’s value itself is not needed inside the loop body.count += 1: Increments the counter by one on each iteration, effectively tallying the total number of elements visited.- Note on
len(): In practice,len(animals)achieves the same result in a single step. The manual loop here is purely for learning purposes and illustrates how element counting works under the hood.
Exercise 4: Check if a Set is Empty
Problem Statement: Write a Python program to check whether a set is empty using conditional logic, and print an appropriate message based on the result.
Purpose: This exercise builds awareness of how Python evaluates collections as truthy or falsy values. Knowing how to check for emptiness reliably prevents bugs in data pipelines, loops, and validation routines where an empty set should trigger a different code path.
Given Input: data = set()
Expected Output: The set is empty.
▼ Hint
- In Python, an empty set is considered falsy. You can use
if not data:to check for emptiness. - Alternatively, compare the set to an empty set using
if data == set():. - Avoid using
if data == {}:as that compares against an empty dictionary, not an empty set.
▼ Solution & Explanation
Solution:
Explanation:
data = set(): Creates an empty set. Note that{}cannot be used here because Python interprets that as an empty dictionary.if not data: Python treats an empty set as falsy, sonot dataevaluates toTruewhen the set has no elements. This is the most idiomatic way to check for emptiness in Python.- Alternative check:
if len(data) == 0orif data == set()are also valid, butif not datais preferred for its clarity and conciseness.
Exercise 5: Union of Sets
Problem Statement: Write a Python program to combine two sets into one, containing all unique elements from both sets.
Purpose: This exercise introduces the union operation, a fundamental concept in set theory and database-style data merging. It is commonly used when aggregating data from multiple sources while automatically eliminating duplicates.
Given Input: set_a = {1, 2, 3, 4} and set_b = {3, 4, 5, 6}
Expected Output: Union: {1, 2, 3, 4, 5, 6}
▼ Hint
- Use the
.union()method:set_a.union(set_b)returns a new set with all elements from both. - Alternatively, use the
|operator:set_a | set_bproduces the same result with cleaner syntax. - Duplicate elements that appear in both sets are automatically included only once in the result.
▼ Solution & Explanation
Solution:
Explanation:
set_a.union(set_b): Returns a new set containing every element from bothset_aandset_b. The original sets are not modified.- Duplicate handling: Elements
3and4appear in both sets but are stored only once in the result, because sets enforce uniqueness by definition. - Operator shorthand:
set_a | set_bis equivalent toset_a.union(set_b)and is often preferred for its brevity in expressions. - Note on ordering: The printed output may appear in a different order each time you run it, since sets are unordered collections and do not guarantee element sequence.
Exercise 6: Intersection of Sets
Problem Statement: Write a Python program to find all elements that are common to both sets.
Purpose: The intersection operation is widely used in filtering, data comparison, and finding overlaps between datasets, such as identifying shared customers, tags, or features across two groups.
Given Input: set_a = {1, 2, 3, 4} and set_b = {3, 4, 5, 6}
Expected Output: Intersection: {3, 4}
▼ Hint
- Use the
.intersection()method:set_a.intersection(set_b)returns only the shared elements. - Alternatively, use the
&operator:set_a & set_bgives the same result. - If the two sets share no elements, the result will be an empty set
set().
▼ Solution & Explanation
Solution:
Explanation:
set_a.intersection(set_b): Returns a new set containing only those elements that appear in bothset_aandset_b. Neither original set is changed.- Result
{3, 4}: These are the only values present in both sets. All other elements are exclusive to one set and are therefore excluded from the intersection. - Operator shorthand:
set_a & set_bproduces the same output asset_a.intersection(set_b)and is more compact for use in expressions. - Empty intersection: If two sets share no common elements, the result is
set(). This is useful for detecting completely disjoint datasets.
Exercise 7: Difference of Sets
Problem Statement: Write a Python program to find all elements that are present in Set A but not in Set B.
Purpose: The difference operation is useful for identifying what is unique to one group compared to another, such as finding items in one inventory but not another, or users who signed up but have not yet completed onboarding.
Given Input: set_a = {1, 2, 3, 4} and set_b = {3, 4, 5, 6}
Expected Output: Difference (A - B): {1, 2}
▼ Hint
- Use the
.difference()method:set_a.difference(set_b)returns elements inset_athat are not inset_b. - Alternatively, use the
-operator:set_a - set_bgives the same result. - Note that
set_a - set_bandset_b - set_aare not the same — order matters here.
▼ Solution & Explanation
Solution:
Explanation:
set_a.difference(set_b): Returns a new set with elements that are inset_abut absent fromset_b. The original sets remain unmodified.- Result
{1, 2}: Elements3and4are excluded because they also appear inset_b. Only the values exclusive toset_aare returned. - Operator shorthand:
set_a - set_bis equivalent toset_a.difference(set_b)and reads naturally as a subtraction of one set from another. - Order matters:
set_b.difference(set_a)would return{5, 6}instead, since that operation finds what is unique toset_b. Unlike union and intersection, difference is not commutative.
Exercise 8: Symmetric Difference
Problem Statement: Write a Python program to find all elements that are in either Set A or Set B, but not in both.
Purpose: The symmetric difference is useful when you need to identify what is exclusive to each group, such as finding products carried by one store but not the other, or detecting changes between two versions of a dataset.
Given Input: set_a = {1, 2, 3, 4} and set_b = {3, 4, 5, 6}
Expected Output: Symmetric Difference: {1, 2, 5, 6}
▼ Hint
- Use the
.symmetric_difference()method:set_a.symmetric_difference(set_b)returns elements unique to each set. - Alternatively, use the
^operator:set_a ^ set_bgives the same result with shorter syntax. - Think of it as the union minus the intersection: elements that appear in one set but not both.
▼ Solution & Explanation
Solution:
Explanation:
set_a.symmetric_difference(set_b): Returns a new set containing elements that belong to exactly one of the two sets. Elements shared by both are excluded from the result.- Result
{1, 2, 5, 6}: Values3and4appear in both sets and are therefore excluded. Only the elements exclusive to each set are retained. - Operator shorthand:
set_a ^ set_bis equivalent toset_a.symmetric_difference(set_b)and is concise for use in expressions. - Commutative property: Unlike
.difference(), symmetric difference is commutative.set_a ^ set_bandset_b ^ set_aalways produce the same result.
Exercise 9: Find Max and Min
Problem Statement: Write a Python program to identify the largest and smallest values in a set of numbers.
Purpose: Finding the range boundaries of a dataset is a common task in data analysis and validation. This exercise also reinforces how Python’s built-in functions operate seamlessly on sets, not just lists.
Given Input: numbers = {42, 7, 19, 85, 3, 56}
Expected Output: Max: 85 and Min: 3
▼ Hint
- Use Python’s built-in
max()function to find the largest element in the set. - Use Python’s built-in
min()function to find the smallest element. - Both functions work directly on sets without needing to convert to a list first.
▼ Solution & Explanation
Solution:
Explanation:
max(numbers): Iterates through the set and returns the highest value found. It works on any iterable, including sets, lists, and tuples.min(numbers): Similarly iterates through the set and returns the lowest value. Both functions complete in a single pass over the data.- No sorting required: Unlike finding the max or min manually, these built-ins do not sort the set. They scan each element once, making them efficient for large datasets.
- Unordered nature of sets: Even though sets have no guaranteed order,
max()andmin()still work correctly because they compare values rather than relying on position.
Exercise 10: Sum of Set Elements
Problem Statement: Write a Python program to calculate the total sum of all elements in a set manually using a loop, without using the built-in sum() function.
Purpose: This exercise reinforces the accumulator pattern using a loop, applied to a set instead of a list. It illustrates that iteration works uniformly across Python collection types and strengthens your grasp of how aggregation functions work internally.
Given Input: numbers = {10, 20, 30, 40, 50}
Expected Output: Sum: 150
▼ Hint
- Initialize a variable
total = 0before the loop to serve as the accumulator. - Use a
forloop to iterate over the set and add each element tototalusing+=. - Print
totalafter the loop completes to display the final sum.
▼ Solution & Explanation
Solution:
Explanation:
total = 0: Sets the accumulator to zero before iteration begins, providing a clean starting point for the running total.for num in numbers: Iterates over each element in the set. Because sets are unordered, the elements may be visited in any sequence, but this does not affect the final sum.total += num: Adds the current element’s value to the running total on each iteration, gradually building up the cumulative sum.- Alternative:
sum(numbers)achieves the same result in a single call. The manual loop here is used deliberately to illustrate the underlying accumulation logic.
Exercise 11: Add a List of Elements
Problem Statement: Write a Python program to add multiple elements from a list into an existing set using the .update() method.
Purpose: This exercise demonstrates how to efficiently bulk-add items to a set from another iterable. The .update() method is preferable to calling .add() in a loop when you have a collection of items ready to merge, and it automatically handles duplicates.
Given Input: fruits = {"apple", "banana"} and new_fruits = ["cherry", "mango", "apple"]
Expected Output: Updated set: {'apple', 'banana', 'cherry', 'mango'}
▼ Hint
- Call
.update()on the existing set and pass the list as the argument:fruits.update(new_fruits). - Unlike
.add(), which accepts only a single element,.update()accepts any iterable including lists, tuples, and other sets. - Duplicate values such as
"apple"in the list will be ignored automatically since sets do not store duplicates.
▼ Solution & Explanation
Solution:
Explanation:
fruits.update(new_fruits): Iterates over every element innew_fruitsand inserts each one intofruitsin place. The original set is modified directly and no new set is created.- Duplicate handling:
"apple"already exists infruitsand also appears innew_fruits. The set silently ignores the duplicate and retains only one copy, preserving the uniqueness guarantee of sets. .update()vs.add():.add()inserts a single element, while.update()unpacks an entire iterable and adds all its elements at once. Using.update()is cleaner and more efficient than looping with.add().- In-place operation:
.update()modifies the set directly and returnsNone. Assigning its result to a variable would storeNone, not the updated set.
Exercise 12: Update with Multiple Iterables
Problem Statement: Write a Python program to add elements from a list, a tuple, and another set into an existing set in a single .update() call.
Purpose: This exercise highlights the flexibility of .update() in accepting multiple iterables at once. It is a practical pattern when consolidating data from several heterogeneous sources into one unified set in a single step.
Given Input: base = {1, 2}, from_list = [3, 4], from_tuple = (5, 6), from_set = {7, 8}
Expected Output: Updated set: {1, 2, 3, 4, 5, 6, 7, 8}
▼ Hint
- Pass all three iterables as separate comma-separated arguments to a single
.update()call:base.update(from_list, from_tuple, from_set). .update()accepts any number of iterable arguments and processes them all in one go.- Any duplicate values across all sources will be merged into a single entry automatically.
▼ Solution & Explanation
Solution:
Explanation:
base.update(from_list, from_tuple, from_set): Accepts multiple iterables as separate arguments and unpacks each one in turn, inserting all their elements intobasein a single operation.- Mixed iterable types:
.update()is type-agnostic. It processes lists, tuples, sets, strings, and any other iterable uniformly, making it highly versatile for merging data from varied sources. - Single call efficiency: Passing all iterables in one
.update()call is equivalent to calling.update()three times separately, but is more readable and slightly more efficient as it reduces method call overhead. - In-place modification: Like all set mutation methods,
.update()modifiesbasedirectly and returnsNone. The merged result lives in the originalbasevariable.
Exercise 13: Check Subset and Superset
Problem Statement: Write a Python program to check whether one set is a subset of another and whether one set is a superset of another using .issubset() and .issuperset().
Purpose: Subset and superset checks are essential in access control systems, tag-based filtering, and data validation scenarios where you need to confirm that one group of items is entirely contained within another.
Given Input: set_a = {1, 2, 3} and set_b = {1, 2, 3, 4, 5}
Expected Output:
Is set_a a subset of set_b? TrueandIs set_b a superset of set_a? True
▼ Hint
- Use
set_a.issubset(set_b)to check if every element ofset_aexists inset_b. - Use
set_b.issuperset(set_a)to check ifset_bcontains all elements ofset_a. - Both methods return a boolean:
TrueorFalse. They can also be written using the operators<=for subset and>=for superset.
▼ Solution & Explanation
Solution:
Explanation:
set_a.issubset(set_b): ReturnsTrueif every element inset_ais also present inset_b. Here,{1, 2, 3}is fully contained within{1, 2, 3, 4, 5}, so the result isTrue.set_b.issuperset(set_a): ReturnsTrueifset_bcontains all elements ofset_a. This is the mirror operation ofissubset()and will always yield the same boolean result when the sets are swapped.- Operator equivalents:
set_a <= set_bis equivalent toset_a.issubset(set_b), andset_b >= set_ais equivalent toset_b.issuperset(set_a). Use<and>for strict subset and superset checks, which returnFalsewhen the sets are equal. - Equal sets: If
set_a == set_b, thenset_a.issubset(set_b)still returnsTruebecause every element of a set is trivially contained within an identical set.
Exercise 14: Intersection Check with isdisjoint()
Problem Statement: Write a Python program to check whether two sets share any common elements using the .isdisjoint() method.
Purpose: Knowing whether two sets are completely separate is valuable in scheduling, access control, and data deduplication tasks, where overlap between groups signals a conflict or an error that needs to be handled.
Given Input: set_a = {1, 2, 3} and set_b = {4, 5, 6}
Expected Output: Are the sets disjoint? True
▼ Hint
- Use
set_a.isdisjoint(set_b)to check if the two sets have no elements in common. - The method returns
Trueif the intersection of the two sets is empty, andFalseif at least one element is shared. - Try changing one of the sets to include a shared element and observe how the result changes.
▼ Solution & Explanation
Solution:
Explanation:
set_a.isdisjoint(set_b): ReturnsTruebecauseset_aandset_bshare no common elements. Internally, Python checks whether the intersection of the two sets is empty.set_a.isdisjoint(set_c): ReturnsFalsebecauseset_ccontains3, which also exists inset_a. Even a single shared element is enough to make two sets non-disjoint.- Efficiency:
.isdisjoint()short-circuits as soon as it finds the first common element, making it faster than computing a full intersection when you only need a boolean answer. - Relationship to intersection:
set_a.isdisjoint(set_b)is logically equivalent tolen(set_a.intersection(set_b)) == 0, but is more readable and more efficient since it avoids constructing the intermediate intersection set.
Exercise 15: Set Difference Update
Problem Statement: Write a Python program to modify a set by removing all elements that are also found in another set using the difference_update() method.
Purpose: This exercise helps you practice in-place set modification. Understanding difference_update() is useful when you need to strip out unwanted or overlapping entries from a collection without creating a new object.
Given Input: a = {1, 2, 3, 4, 5} and b = {3, 4, 5, 6, 7}
Expected Output: a = {1, 2}
▼ Hint
- Call
a.difference_update(b)to remove fromaany element that also appears inb. - This modifies
ain place – it does not return a new set. - After the call,
awill only contain elements that were never inb.
▼ Solution & Explanation
Explanation:
a.difference_update(b): Removes every element fromathat is also present inb. Unlikea - b, which returns a new set, this method updatesadirectly.- In-place modification: The original set
ais changed. The method returnsNone, so avoid assigning its result to a variable. - Elements in
bbut not ina: Values like6and7exist only inband are simply ignored during the operation.
Exercise 16: Set Intersection Update
Problem Statement: Write a Python program to modify a set so that it keeps only the elements that are also found in another set using the intersection_update() method.
Purpose: This exercise reinforces in-place filtering of a set to its shared elements. It is commonly used when reconciling two collections and retaining only the data that appears in both, such as matching user IDs or common tags.
Given Input: a = {1, 2, 3, 4, 5} and b = {3, 4, 5, 6, 7}
Expected Output: a = {3, 4, 5}
▼ Hint
- Call
a.intersection_update(b)to keep only the elements that appear in bothaandb. - This modifies
ain place and returnsNone. - Any element in
athat is not also inbwill be discarded.
▼ Solution & Explanation
Explanation:
a.intersection_update(b): Retains only the elements that are common to bothaandb, discarding everything else froma.- In-place modification: The set
ais updated directly. This differs froma & bora.intersection(b), both of which return a new set and leaveaunchanged. - Result: Only
{3, 4, 5}survive because those are the values present in both sets. Elements1and2are removed froma, and6and7were never inato begin with.
Exercise 17: Set Symmetric Difference Update
Problem Statement: Write a Python program to modify a set so that it keeps only elements that are in either set but not in both, using the symmetric_difference_update() method.
Purpose: This exercise teaches you to isolate non-overlapping elements between two sets in place. It is useful in scenarios like finding items that exist in one dataset but not the other, such as detecting mismatches between two records.
Given Input: a = {1, 2, 3, 4, 5} and b = {3, 4, 5, 6, 7}
Expected Output: a = {1, 2, 6, 7}
▼ Hint
- Call
a.symmetric_difference_update(b)to keep only elements that appear in exactly one of the two sets. - Elements present in both sets are removed from
a; elements only inbare added toa. - This method modifies
ain place and returnsNone.
▼ Solution & Explanation
Explanation:
a.symmetric_difference_update(b): Updatesato contain only elements that are in exactly one of the two sets. Shared elements (3,4,5) are removed, and elements unique tob(6,7) are added.- In-place modification: The set
ais changed directly. The equivalent expressiona ^= bproduces the same result and is a more compact alternative. - Symmetric nature: The operation is symmetric in outcome (the non-overlapping union), but the update always targets the set on which the method is called – in this case
a.
Exercise 18: Remove Items Simultaneously
Problem Statement: Write a Python program to remove a batch of specific items from a set all at once using the difference_update() method.
Purpose: This exercise demonstrates a practical use of difference_update() as a bulk-removal tool. Rather than looping and calling remove() repeatedly, you can pass a collection of items to discard in a single operation.
Given Input: items = {10, 20, 30, 40, 50, 60} and to_remove = {20, 40, 60}
Expected Output: items = {10, 30, 50}
▼ Hint
- Define your set of values to remove as a separate set or list:
to_remove = {20, 40, 60}. - Call
items.difference_update(to_remove)to remove all those values fromitemsat once. - Any value in
to_removethat does not exist initemsis safely ignored – no error is raised.
▼ Solution & Explanation
Explanation:
items.difference_update(to_remove): Removes all elements into_removefromitemsin a single call. This is more concise and efficient than callingitems.remove()individually for each value.- No
KeyErroron missing values: If a value into_removeis not present initems, it is silently skipped. This makes the operation safer thanremove(), which raises aKeyErrorfor missing elements. - Accepts any iterable: The argument to
difference_update()can be a set, list, or tuple – any iterable of hashable values will work.
Exercise 19: The Pop Operation
Problem Statement: Write a Python program to remove and return an arbitrary element from a set using pop(), and handle the KeyError that occurs when the set is empty.
Purpose: This exercise familiarises you with the pop() method and its unpredictable nature on sets. It also practices defensive programming using try/except blocks to handle runtime errors gracefully.
Given Input: s = {100, 200, 300} and then an empty set s = set()
Expected Output:
Popped: 100 (or any arbitrary element) Error: pop from an empty set
▼ Hint
- Use
s.pop()to remove and return one element. Sets are unordered, so you cannot predict which element will be returned. - Wrap the
pop()call on an empty set inside atry/except KeyErrorblock to catch the error cleanly. - Use
set()(not{}) to create an empty set –{}creates an empty dictionary.
▼ Solution & Explanation
Explanation:
s.pop(): Removes and returns an arbitrary element from the set. Because sets are unordered, there is no guarantee which element will be returned – do not rely on a specific value.try/except KeyError: Whenpop()is called on an empty set, Python raises aKeyError. Wrapping the call in atryblock prevents the program from crashing and allows you to respond to the error gracefully.set()vs{}: An empty set must be created withset(). Using{}produces an empty dictionary, which is a common source of bugs when working with sets.
Exercise 20: Filter a Set
Problem Statement: Write a Python program to create a new set containing only the elements from an existing set that satisfy a condition – specifically, elements divisible by 3.
Purpose: This exercise introduces set comprehensions as a clean and readable way to filter data. The pattern mirrors list comprehensions but produces a set, which automatically eliminates any duplicate results.
Given Input: numbers = {1, 2, 3, 6, 7, 9, 12, 14, 15}
Expected Output: divisible_by_3 = {3, 6, 9, 12, 15}
▼ Hint
- Use a set comprehension:
{x for x in numbers if x % 3 == 0}. - The
%operator returns the remainder of a division. Ifx % 3 == 0, thenxis divisible by 3. - The result is a new set – the original
numbersset remains unchanged.
▼ Solution & Explanation
Explanation:
{x for x in numbers if x % 3 == 0}: A set comprehension that iterates over every element innumbersand includes it in the result only if it passes the conditionx % 3 == 0.x % 3 == 0: The modulo operator%returns the remainder after division. A remainder of zero confirms the number divides evenly by 3.- Non-destructive: The original set
numbersis not modified. The filtered result is stored in the new variabledivisible_by_3.
Exercise 21: Find Common Elements in Lists
Problem Statement: Write a Python program to find the common elements between two lists by converting them to sets and using the intersection operation.
Purpose: This exercise shows how sets can solve a practical problem more elegantly than nested loops. Converting lists to sets before intersecting them removes duplicates and enables fast lookup, making the approach both concise and efficient.
Given Input: list1 = [1, 2, 3, 4, 5, 3, 2] and list2 = [3, 4, 5, 6, 7, 4, 5]
Expected Output: common = {3, 4, 5}
▼ Hint
- Convert both lists to sets using
set(list1)andset(list2). - Use the
&operator or the.intersection()method to find shared elements. - Duplicates in the original lists are automatically removed during the
set()conversion, so the result will contain each common value only once.
▼ Solution & Explanation
Explanation:
set(list1)andset(list2): Converts each list into a set, which removes duplicate values and enables set operations.list1becomes{1, 2, 3, 4, 5}andlist2becomes{3, 4, 5, 6, 7}.&operator: Performs a set intersection, returning a new set containing only the elements present in both sets. This is equivalent to callingset(list1).intersection(set(list2)).- Efficiency advantage: Compared to a nested loop approach, set intersection runs in average O(min(n, m)) time, making it significantly faster for large lists.
Exercise 22: Count Unique Words
Problem Statement: Write a Python program to process a string and find the total number of unique words it contains, ignoring case differences.
Purpose: This exercise shows how sets can be used to deduplicate data from a real-world source. Converting words to a set is a fast and idiomatic way to count distinct tokens, a technique used in text analysis, search engines, and natural language processing pipelines.
Given Input: text = "the cat sat on the mat the cat"
Expected Output: Unique word count: 5
▼ Hint
- Use
text.lower().split()to normalise case and split the string into a list of words. - Pass the resulting list to
set()to remove duplicates automatically. - Use
len()on the set to get the count of unique words.
▼ Solution & Explanation
Explanation:
text.lower(): Converts the entire string to lowercase so that words like"The"and"the"are treated as the same word during deduplication..split(): Splits the string on whitespace and returns a list of individual word tokens. No separator argument is needed for standard space-separated text.set(words): Constructs a set from the list, which discards all duplicate entries. Only one instance of each unique word is retained.len(unique_words): Returns the number of elements in the set, which equals the number of distinct words. Here,"the"and"cat"each appear multiple times but are counted only once, giving a result of5.
Exercise 23: Convert Set to Joined String
Problem Statement: Write a Python program to convert a set of words into a single string where each element is separated by a specified delimiter.
Purpose: This exercise practises combining set data back into a human-readable string. Joining a set is commonly needed when generating comma-separated values, building display labels from tags, or serialising a set of identifiers into a single field.
Given Input: tags = {"python", "set", "programming", "tutorial"}
Expected Output: A single string with all tags joined by " | " (order may vary)
▼ Hint
- Use
" | ".join(tags)to concatenate all elements with the delimiter between them. - All elements in the set must be strings. If they are not, convert them with a generator expression:
" | ".join(str(x) for x in tags). - Sets are unordered, so the output sequence will vary each run. Use
sorted(tags)first if consistent ordering is required.
▼ Solution & Explanation
Explanation:
" | ".join(...): Thestr.join()method takes an iterable and concatenates its elements into one string, placing the delimiter string between each pair. The delimiter itself does not appear at the start or end.sorted(tags): Converts the set into a sorted list before joining. Because sets are unordered, skipping this step would produce a different element sequence on each run, making the output unpredictable.- Type requirement:
join()requires all elements to be strings. If the set contained integers or other types, you would need" | ".join(str(x) for x in sorted(tags))to convert each element first.
Exercise 24: Proper Subset and Superset
Problem Statement: Write a Python program to check whether one set is a proper subset and another is a proper superset using the < and > operators.
Purpose: This exercise clarifies the difference between regular and proper subset/superset relationships. Understanding strict comparisons is useful when validating permissions, checking feature flag hierarchies, or verifying that one group of items is strictly contained within another.
Given Input: a = {1, 2, 3} and b = {1, 2, 3, 4, 5}
Expected Output:
a is a proper subset of b: True b is a proper superset of a: True a is a proper subset of a: False
▼ Hint
- Use
a < bto check ifais a proper subset: every element ofais inb, andbhas at least one additional element. - Use
b > ato check ifbis a proper superset ofa. - A set is never a proper subset of itself. Try
a < ato confirm it returnsFalse, whereasa <= areturnsTrue.
▼ Solution & Explanation
Explanation:
a < b: ReturnsTrueonly if every element inaexists inbandbcontains at least one element not ina. Both conditions must hold simultaneously.b > a: The mirror ofa < b. ReturnsTrueifbstrictly contains all ofaand is larger. This is equivalent tob.issuperset(a) and b != a.a < a: ReturnsFalsebecause a set cannot be a proper subset of itself – the sets are equal, not strictly contained. Usea <= a(ora.issubset(a)) when you want to allow the equal case.
Exercise 25: Frozen Set
Problem Statement: Write a Python program to create a frozenset, demonstrate that set operations work on it, and confirm that any attempt to modify it raises a TypeError.
Purpose: This exercise introduces immutability in the context of sets. A frozenset can be used as a dictionary key or stored inside another set, making it valuable when you need a hashable, read-only collection, such as representing a fixed combination of permissions or configuration flags.
Given Input: fs = frozenset([1, 2, 3, 4, 5])
Expected Output:
frozenset: frozenset({1, 2, 3, 4, 5})
Intersection with {3, 4, 5, 6}: frozenset({3, 4, 5})
Error: 'frozenset' object has no attribute 'add'
▼ Hint
- Create a frozenset using
frozenset([...])orfrozenset({...}). - Read-only operations like
intersection(),union(), andinmembership testing all work normally on a frozenset. - Wrap a mutation attempt such as
fs.add(6)in atry/except AttributeErrorblock to catch the error cleanly and print a helpful message.
▼ Solution & Explanation
Explanation:
frozenset([1, 2, 3, 4, 5]): Constructs an immutable set from the given iterable. Like a regular set, it stores only unique, hashable elements – but once created, its contents can never change.fs.intersection({3, 4, 5, 6}): Non-mutating operations are fully supported. Methods likeintersection(),union(),difference(), andissubset()all return new frozensets or booleans without touching the original.fs.add(6): Raises anAttributeErrorbecausefrozensetdoes not implement mutation methods such asadd,remove, ordiscard. The error message reads:'frozenset' object has no attribute 'add'.- Use as a dictionary key: Because frozensets are hashable, you can use them as dictionary keys or store them inside regular sets – something a mutable
setcannot do.
Exercise 26: Set Comprehension
Problem Statement: Write a Python program to generate a set of squares of all even numbers from 1 to 20 using a set comprehension in a single line.
Purpose: This exercise demonstrates set comprehensions as a concise and readable alternative to building sets with loops. They follow the same syntax as list comprehensions but produce a set, ensuring all resulting values are automatically deduplicated.
Given Input: Numbers from 1 to 20 (inclusive)
Expected Output: {4, 16, 36, 64, 100, 144, 196, 256, 324, 400}
▼ Hint
- Use a set comprehension with curly braces:
{x**2 for x in range(1, 21) if x % 2 == 0}. - The condition
if x % 2 == 0filters the range to even numbers only before squaring. - Use
x**2orx*xto compute the square of each number.
▼ Solution & Explanation
Explanation:
{x**2 for x in range(1, 21) if x % 2 == 0}: A set comprehension with three parts: the expressionx**2defines what goes into the set,for x in range(1, 21)iterates from 1 to 20, andif x % 2 == 0restricts processing to even numbers.- Automatic deduplication: If the expression could produce repeated values (for example, squaring both
-2and2), the set would silently keep only one copy. This is a key advantage of set comprehensions over list comprehensions when uniqueness matters. - Unordered output: The printed result may not appear in ascending order. If sorted output is needed, wrap the set in
sorted():print(sorted(squares_of_evens)).
Exercise 27: Remove Duplicates (Preserving Order)
Problem Statement: Write a Python program to remove duplicate values from a list while preserving the original order of first appearances.
Purpose: Converting a list directly to a set removes duplicates but loses order. This exercise teaches a practical pattern that combines the deduplication power of a set with the ordering properties of a list, commonly needed in data cleaning, deduplication pipelines, and maintaining insertion-ordered unique sequences.
Given Input: items = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
Expected Output: [3, 1, 4, 5, 9, 2, 6]
▼ Hint
- Maintain an empty set called
seenand an empty list calledresult. - Loop through
items: if the current item is not inseen, append it toresultand add it toseen. - The set provides O(1) average-time membership testing, making the overall loop efficient even for large lists.
▼ Solution & Explanation
Explanation:
seen = set(): Acts as a fast lookup table. Checking membership withinon a set is O(1) on average, compared to O(n) for a list. This makes the algorithm efficient even as the input grows.if item not in seen: The first time an item is encountered, this condition isTrueand the item is appended toresult. On all subsequent appearances, the item is already inseenand is skipped.- Order is preserved: Unlike
list(set(items)), which discards insertion order, this approach guarantees that elements appear in the result in the same order as their first occurrence in the input.
Exercise 28: Multi-Set Difference
Problem Statement: Write a Python program to find all elements that are in Set A but not present in either Set B or Set C.
Purpose: This exercise extends the two-set difference operation to multiple sets. It is practical in scenarios such as finding users who have not yet completed any of several onboarding steps, or items in a master list that have not been processed by any of several workers.
Given Input:
A = {1, 2, 3, 4, 5, 6, 7, 8}B = {2, 4, 6}C = {5, 7, 9}
Expected Output: Result: {1, 3, 8}
▼ Hint
- Chain the
difference()method:A.difference(B, C)removes all elements found in eitherBorCfromAin one call. - Alternatively, use the
-operator twice:A - B - C. - You can also compute
A - (B | C), which first unionsBandC, then subtracts the combined set fromA.
▼ Solution & Explanation
Explanation:
A.difference(B, C): Returns a new set containing every element ofAthat does not appear inBor inC. Passing multiple arguments todifference()is equivalent to subtracting all of them at once and is more readable than chaining-operators.- Elements in C not in A: The value
9is inCbut not inA. It has no effect on the result because the operation only removes elements that exist inA. - Equivalent expressions:
A - B - CandA - (B | C)both produce the same result. Thedifference()method form is preferred when subtracting more than two sets, as it reads more clearly and avoids intermediate set creation.
Exercise 29: Set of Tuples
Problem Statement: Write a Python program to demonstrate that a set can store tuples as elements but cannot store lists, and explain why this difference exists.
Purpose: This exercise builds a concrete understanding of hashability, the property that determines which types can live inside a set or be used as dictionary keys. Knowing why lists are rejected and tuples are accepted prevents common bugs when working with collections of compound values.
Given Input: A set containing tuples, then an attempt to add a list as an element
Expected Output:
Set of tuples: {(1, 2), (3, 4), (5, 6)}
Error: unhashable type: 'list'
▼ Hint
- Create a set with tuple elements directly using curly brace syntax:
{(1, 2), (3, 4), (5, 6)}. - Attempt to create a set containing a list element, such as
{[1, 2], [3, 4]}, inside atry/except TypeErrorblock. - Tuples are hashable because they are immutable. Lists are not hashable because they can be modified after creation, which would invalidate any hash-based lookup.
▼ Solution & Explanation
Explanation:
- Hashability requirement: Python sets use a hash table internally. Every element must have a stable hash value, computed once and used to determine its storage slot. An object is hashable if it implements
__hash__()and__eq__(), and if its hash cannot change over its lifetime. - Tuples are hashable: Because tuples are immutable, their contents can never change after creation. Python can safely compute and store a hash for them, making tuples valid set elements and valid dictionary keys.
- Lists are not hashable: Lists are mutable – you can append, remove, or change elements at any time. If a list were stored in a set and then mutated, its hash would change and the set would no longer be able to find it. Python prevents this entirely by making lists unhashable, raising a
TypeErroron any attempt to hash them.
Exercise 30: Shallow Copy vs. Assignment
Problem Statement: Write a Python program to demonstrate the difference between assigning a set to a new variable with = and creating an independent copy using the .copy() method.
Purpose: This exercise addresses one of the most common sources of subtle bugs in Python: confusing reference assignment with object copying. Understanding this distinction is essential whenever you intend to work with a separate version of a collection without affecting the original.
Given Input: original = {1, 2, 3, 4, 5}
Expected Output:
--- Assignment (=) ---
original: {1, 2, 3, 4, 5, 99}
ref: {1, 2, 3, 4, 5, 99}
--- Shallow copy (.copy()) ---
original: {1, 2, 3, 4, 5}
copied: {1, 2, 3, 4, 5, 42}
▼ Hint
- Use
ref = originalto create a reference, then add an element torefand observe thatoriginalis also modified – they point to the same object. - Use
copied = original.copy()to create an independent set, then add an element tocopiedand confirm thatoriginalis unchanged. - You can also use
set(original)as an alternative to.copy()to produce the same independent copy.
▼ Solution & Explanation
Explanation:
ref = original: This does not create a new set. Bothrefandoriginalare names that refer to the exact same object in memory. Any mutation through one name is immediately visible through the other.original.copy(): Creates a new, independent set object that starts with the same elements. Mutations tocopieddo not affectoriginal, and mutations tooriginaldo not affectcopied.- Why “shallow”: For a set of immutable elements (numbers, strings, tuples), shallow copy is sufficient. If the set contained mutable objects (which sets cannot, by the hashability rule), a shallow copy would still share those inner objects. For sets specifically,
.copy()is always safe because all valid set elements are immutable.
Exercise 31: Membership Testing Performance
Problem Statement: Write a Python program to compare the time taken to check whether an item exists in a large list versus a large set, and observe the performance difference.
Purpose: This exercise makes the performance advantage of sets concrete and measurable. Membership testing is one of the most frequent operations in programming, and switching from a list to a set can reduce lookup time from O(n) to O(1) on average – a critical optimisation for large datasets.
Given Input: A range of 1,000,000 integers, searching for 999999
Expected Output:
List lookup time: 0.008542 seconds Set lookup time: 0.000001 seconds
▼ Hint
- Use the
timemodule: recordtime.time()before and after each lookup, then subtract to find elapsed time. - Create the list with
list(range(1_000_000))and the set withset(range(1_000_000)). - Search for
999999(the last element) to force the list to scan all the way to the end, maximising the performance gap.
▼ Solution & Explanation
Explanation:
- List membership – O(n): The
inoperator on a list performs a linear scan from the first element to the last. In the worst case (the target is at the end or absent), Python checks every element. For a list of 1,000,000 items, this means up to 1,000,000 comparisons. - Set membership – O(1) average: The
inoperator on a set computes the hash of the target and looks up the corresponding slot in the hash table directly. Regardless of how many elements the set contains, this typically completes in one or two steps. - Practical implication: If you need to perform many membership tests against a fixed collection, convert the collection to a set once upfront. The one-time conversion cost of
set(large_list)is quickly recovered when each subsequent lookup is thousands of times faster than the list equivalent.
