1.2.25 · D5Introduction to Programming (Python)
Question bank — Sets — unique elements, set operations (union, intersection, difference)
Vocabulary reminder before we start, so no symbol appears unearned:
- = union = "in OR " (the wall
|). - = intersection = "in AND " (the net
&). - = difference = "in but NOT ".
- = symmetric difference = "in exactly ONE of them" (the hat
^). - Hashable = an object whose contents can't change, so Python can compute a stable address (hash) for it. Immutable things (numbers, strings, tuples) qualify; mutable things (lists, dicts, sets) don't.
True or false — justify
Adding 2 to a set that already contains 2 raises an error.
False. A duplicate insert is silently ignored — the set already has that "membership stamp", so nothing changes and no error is raised.
{} is an empty set.
False.
{} is an empty dictionary; Python broke the tie in favour of dicts. An empty set is only ever set().A - B and B - A always give the same result.
False. Difference is not symmetric:
A - B is "in A but not B", B - A is "in B but not A". They're equal only when (both give the empty set).For any sets, A ^ B equals (A | B) - (A & B).
True. Symmetric difference = everything in either, minus the shared middle — exactly the "in exactly one" elements. This is an identity, true for all inputs including empty sets.
A & B is always a subset of A.
True. Intersection keeps only elements that are in A (AND also in B), so every element it produces was already in A — never more.
A | B can be smaller than A.
False. Union contains everything in A plus possibly more, so always. It can equal (when ) but never shrink below it.
Sets always print their elements in the order you inserted them.
False. Sets are organized by hash, not insertion order. Small integers may look ordered by coincidence; never rely on it — use
sorted(s) when order matters.{(1, 2), 3} is a valid set.
True. A tuple is immutable and therefore hashable, so it's a legal set element. Contrast
{[1, 2], 3}, which fails because a list is mutable/unhashable.A.union(B) changes A.
False.
union returns a new set and leaves A untouched. The mutating version is A.update(B) (or A |= B).If x in s is True for a set, Python scanned every element to find x.
False. A set jumps directly to the bucket given by
hash(x) and checks there — roughly . Scanning every element is what a list does ().The empty set is a subset of every set.
True. "Subset" means every element of it is also in the other set; the empty set has no elements to violate this, so the condition is vacuously satisfied.
A ^ A is always empty.
True. Symmetric difference asks "in exactly one" — but every element of A is in both copies, so none qualifies. Result:
set().Spot the error
s = {} then s.add(5) — will this behave like a set?
No.
{} made a dict, so s.add(5) raises AttributeError — dicts have no .add. Use s = set() first.s = {1, 2, 3} then print(s[0]) to get the first element.
Error. Sets are unindexed — there's no "position 0", so
s[0] raises TypeError. Use sorted(s)[0] or iterate if you need an element.unique = list(set(names)) guarantees the original order.
Wrong guarantee. It dedups correctly but loses order (hash order). For first-seen order use
list(dict.fromkeys(names)).tags = {["a", "b"], "c"} to store a group of tags.
TypeError: unhashable type: 'list'. A list can change, so its hash could change — sets forbid it. Wrap in a tuple: {("a", "b"), "c"}.shared = a1.union(a2) to find tags common to both articles.
Wrong operation.
union gives everything in either; "common to both" is intersection — use a1 & a2 (i.e. a1.intersection(a2)).C = A.update(B) to build the union into a new variable C.
Bug:
update mutates A in place and returns None, so C becomes None. For a new set use C = A | B or C = A.union(B).{1, 2, 3} == [1, 2, 3] should be True since they hold the same numbers.
False. A set never equals a list — different types. Also the set is unordered; equality across these containers is always
False.Why questions
Why is checking membership in a set faster than in a list?
A list has no map from value to location, so worst case it compares against all entries (). A set hashes the value straight to one bucket (), independent of size. See Big-O Notation & Time Complexity.
Why can numbers, strings and tuples live in a set but not lists or dicts?
Set elements must be hashable — their hash must never change. Immutable objects qualify; mutable ones (list, dict, set) could change after insertion and corrupt the address, so they're banned. See Hashing and Hashable Types.
Why does adding a duplicate silently vanish instead of raising an error?
A set models pure membership: "in or out". Being in twice is meaningless, so the second insert is a harmless no-op — treating it as an error would break the whole convenience of dedup.
Why is A - B NOT the same as B - A while A ^ B IS the same as B ^ A?
Plain difference is directional — "in the first but not the second" depends on which is first. Symmetric difference asks "in exactly one", which doesn't care about order, so swapping A and B leaves it unchanged.
Why did Python give {} to dictionaries instead of sets?
Dicts (
{key: value}) came first and already owned curly-brace literals. A tie had to be broken; the empty-braces case went to dict, leaving sets to use set().Why does A ^ B == (A | B) - (A & B) hold?
The union holds every element in either set; the intersection is the double-counted middle. Removing that middle leaves only elements exclusive to one set — the literal meaning of symmetric difference. See Boolean Logic — AND, OR, XOR.
Why is the intersection of two sets never larger than the smaller of the two?
Every element of the intersection must be in BOTH sets, so it can't exceed the elements available in either — in particular it's bounded by the smaller set's size.
Edge cases
What is set() | {1, 2}?
{1, 2}. Union with the empty set adds nothing new, so you get the other set unchanged — the empty set is the "identity" for union.What is {1, 2} & set()?
set(). Nothing is in BOTH a set and the empty set, so intersection with empty is always empty — the "annihilator" for intersection.What is A - A for any set A?
set(). Every element of A is also in A, so "in A but not A" is impossible — nothing survives.What is {1, 2, 3} ^ set()?
{1, 2, 3}. Elements in exactly one of the two: since the second is empty, every element of the first qualifies — the empty set is the identity for symmetric difference too.What does len({1, 1, 1, 1}) return, and why?
1. All four 1s collapse to a single stamp at insertion time, so the stored set is just {1} with length 1.Is set() "falsy"? What does if set(): do?
Yes — an empty set is falsy, so
if set(): runs the else branch (skips the body). Any non-empty set is truthy.Can a set contain another set as an element?
No — a regular
set is mutable/unhashable. To nest, the inner one must be a frozenset (the immutable, hashable set variant): {frozenset({1, 2}), 3} is valid.Does {1, True} have one element or two, and why?
One element. In Python
1 == True and hash(1) == hash(True), so True is treated as a duplicate of 1 — the set keeps whichever landed first: {1}.Connections
- Lists — ordered, indexed collections — the ordered, indexable counterpart these traps contrast against.
- Dictionaries — key-value & why {} is a dict — why
{}is a dict, not a set. - Hashing and Hashable Types — the reason lists can't be elements.
- Tuples — immutable sequences — the hashable fix for grouped elements.
- Big-O Notation & Time Complexity — the vs membership claim.
- Boolean Logic — AND, OR, XOR — the AND/OR/XOR skeleton under the set operations.