Sets & Frozensets Interview Questions & Answers

6 questions Updated 2026-06-18

Python interview questions on set operations, O(1) membership vs lists, deduplication, add/discard/remove, frozensets, and set comprehensions.

Sets support the classic mathematical operations, each with an operator and an equivalent method: union (|), intersection (&), difference (-), and symmetric difference (^, items in exactly one set).

a = {1, 2, 3}
b = {2, 3, 4}

a | b    # {1, 2, 3, 4}      union — in either
a & b    # {2, 3}            intersection — in both
a - b    # {1}               difference — in a, not b
a ^ b    # {1, 4}            symmetric difference — in one, not both

a.union(b)              # method form, accepts any iterable
a.intersection([2, 3])  # b can be a list here

The operator forms require both operands to be sets, while the method forms accept any iterable. Use them for fast "what's common / unique / missing" questions instead of nested loops.

A set is backed by a hash table, so x in s is average O(1) — it hashes x and checks one bucket. A list has no such index, so x in lst is O(n) — it scans elements one by one until it finds a match or reaches the end.

big_list = list(range(1_000_000))
big_set  = set(big_list)

999_999 in big_list   # O(n) — scans up to a million items
999_999 in big_set    # O(1) — single hash lookup

For repeated membership checks over a large collection, converting to a set first is a huge win. The trade-off is that sets are unordered and elements must be hashable. Rule of thumb: if you mostly ask "is X in here?", use a set, not a list.

Wrapping a list in set() removes duplicates instantly, since a set can't hold repeated values. The catch is that a set is unordered, so this doesn't preserve the original order.

nums = [3, 1, 2, 3, 1]
unique = list(set(nums))      # e.g. [1, 2, 3] — order NOT guaranteed

# order-preserving dedup (dict keys are unique AND ordered since 3.7):
ordered = list(dict.fromkeys(nums))   # [3, 1, 2]

Use set() when you only care about the distinct values; when order matters, use dict.fromkeys(), which keeps first-seen order thanks to guaranteed dict ordering. Both require the elements to be hashable.

add(x) inserts an element (a no-op if it's already present). To delete, remove(x) raises KeyError if the element is missing, while discard(x) removes it silently if present and does nothing otherwise.

s = {1, 2, 3}
s.add(2)          # already there — no change
s.add(4)          # {1, 2, 3, 4}

s.remove(4)       # {1, 2, 3}
s.remove(99)      # KeyError — not in set
s.discard(99)     # no error, no change
s.pop()           # removes and returns an arbitrary element

Choose discard when "remove if it's there" is the intent (no need to guard with a membership check), and remove when a missing element is genuinely an error you want surfaced. pop() removes an arbitrary element since sets are unordered.

A frozenset is the immutable version of set — it supports all the read operations (union, intersection, membership) but has no add/remove. Because it's immutable, it's hashable, so it can be a dict key or an element of another set.

fs = frozenset([1, 2, 3])
fs.add(4)              # AttributeError — immutable
fs & {2, 3, 4}         # frozenset({2, 3}) — set ops still work

{fs: "a group"}        # usable as a dict key
{frozenset({1, 2}), frozenset({3, 4})}   # a set OF sets

The classic use is a set of sets: regular sets are unhashable, so the inner ones must be frozensets. Also use a frozenset for a constant collection you want to guarantee can't be mutated. Reach for it whenever you need a set-like value that must be hashable.

A set comprehension builds a set in one expression with {expr for item in iterable}, automatically deduplicating the results. It's the set sibling of list and dict comprehensions, with curly braces and no key:value pair.

squares = {n * n for n in range(-3, 4)}
# {0, 1, 4, 9} — note 9 appears once even though -3 and 3 both map to it

words = ["Hi", "hi", "HEY"]
lowered = {w.lower() for w in words}   # {'hi', 'hey'}

It's ideal when you want unique transformed values in a single readable step. Watch out that {} alone is an empty dict, not an empty set — use set() for an empty set. Use a set comprehension when both transformation and deduplication are the goal.

Practice tests are coming soon

Get notified when interactive mock interviews and quizzes launch.