Skip to content
VLSI Mentor

Python Part I · Module 7 · Sets

Set Operations: Difference, Union, Intersection

This is what the previous three chapters were building towards. Given the failures from yesterday's run and the failures from today's, there are four questions worth asking, and every one of them is a single line of Python. The operations have mathematical names and single-character symbols, and learning them in that form is the reason so many people can recite what intersection means and still not reach for it when the question in front of them is which tests broke overnight. So this chapter starts from the questions. The symbols arrive once each question already has an answer, and one of them has a direction that it is genuinely easy to get backwards.

Foundation15 min readPythonPart IFundamentalsSetsOperations

Part I · Module 7 · Chapter 7.4 · Set Operations: Difference, Union, Intersection

1. Four Questions About Two Runs

Here is the data, and it is the same data Chapter 7.1 opened with:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
yesterday = {"reset", "timeout", "crc"}
today = {"timeout", "crc", "interrupt"}

Three failures each. Some overlap. The four questions a reviewer asks, in plain English:

  1. What is failing today that was not failing yesterday? — something broke.
  2. What was failing yesterday and is not failing today? — something got fixed.
  3. What is failing in both? — the persistent ones, probably the real work.
  4. What failed in either run? — everything that needs looking at.

Each has a one-line answer. Take them in order, and notice that the English question comes first every time — if you only remember the symbol, you will not know which one to reach for.

2. What Broke: today - yesterday

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
yesterday = {"reset", "timeout", "crc"}
today = {"timeout", "crc", "interrupt"}
new_fails = today - yesterday
print(sorted(new_fails))
print(len(new_fails))
print(new_fails == {"interrupt"})
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['interrupt']
1
True

today - yesterday gives the elements that are in today and not in yesterday. One test — interrupt — is failing now and was not before. That is the new problem.

The operation is called difference, and read aloud today - yesterday is "today, minus anything that was already in yesterday".

Three ways of confirming the answer are shown there on purpose: sorted() to read it, len() to count it, and == against the set you expected. All three are reproducible, and Chapter 7.2 explains why printing new_fails directly would not be.

3. What Got Fixed: yesterday - today

Same operator. Operands swapped:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
yesterday = {"reset", "timeout", "crc"}
today = {"timeout", "crc", "interrupt"}
fixed = yesterday - today
print(sorted(fixed))
print(len(fixed))
print(fixed == {"reset"})
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['reset']
1
True

yesterday - today gives what was failing yesterday and is not failing now. reset has stopped failing.

Put the two side by side, because this is the single most important thing in the chapter:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
yesterday = {"reset", "timeout", "crc"}
today = {"timeout", "crc", "interrupt"}
print(sorted(today - yesterday))
print(sorted(yesterday - today))
print((today - yesterday) == (yesterday - today))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['interrupt']
['reset']
False

Both results have one element. Both are plausible-looking answers. They mean opposite things — one is a regression and the other is a fix — and nothing in the output would tell you which one you computed.

A useful way to remember it: - on sets reads like - on numbers. You start with the thing on the left and take away from it.

4. What Failed in Both: today & yesterday

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
yesterday = {"reset", "timeout", "crc"}
today = {"timeout", "crc", "interrupt"}
both = today & yesterday
print(sorted(both))
print(len(both))
print(both == {"timeout", "crc"})
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['crc', 'timeout']
2
True

& gives the elements present in both sets — the intersection. Two tests failed yesterday and are still failing today.

These are usually the ones that matter most in a review: not a new breakage, not a fix, but a problem that has survived a day of work.

5. What Failed in Either: today | yesterday

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
yesterday = {"reset", "timeout", "crc"}
today = {"timeout", "crc", "interrupt"}
either = today | yesterday
print(sorted(either))
print(len(either))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['crc', 'interrupt', 'reset', 'timeout']
4

| gives everything in either set — the union. Four distinct tests were involved across the two runs.

Note the count. Three plus three is six, and the answer is four, because timeout and crc appear in both and a set holds each distinct value once. Union combines membership; it does not stack collections up.

The fourth operation: what changed either way

The module covers four operations, and this is the one the title does not name:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
yesterday = {"reset", "timeout", "crc"}
today = {"timeout", "crc", "interrupt"}
changed = today ^ yesterday
print(sorted(changed))
print(len(changed))
print(changed == {"reset", "interrupt"})
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['interrupt', 'reset']
2
True

^ gives the elements in one set or the other but not both — the symmetric difference. In review terms: everything that changed overnight, whether it broke or got fixed, with the unchanged failures left out.

It is exactly the two differences from Sections 2 and 3 combined, which you can verify:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
yesterday = {"reset", "timeout", "crc"}
today = {"timeout", "crc", "interrupt"}
print((today ^ yesterday) == (today - yesterday) | (yesterday - today))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
True

Unlike -, this one has no direction to get wrong — Section 7 shows why.

6. The Originals Are Untouched

Every operation in this chapter builds a new set and changes neither operand:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
yesterday = {"reset", "timeout", "crc"}
today = {"timeout", "crc", "interrupt"}
new_fails = today - yesterday
both = today & yesterday
either = today | yesterday
print(sorted(today))
print(sorted(yesterday))
print(len(today), len(yesterday))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['crc', 'interrupt', 'timeout']
['crc', 'reset', 'timeout']
3 3

Three and three, exactly as they started, after three operations.

This is worth noticing because Chapter 7.3 was entirely about changing a set in place. These are operators, not methods, and they behave like every operator in Module 3: they take values and produce a value. today - yesterday no more changes today than a - b changes a.

7. Which Operations Have a Direction

Three of the four give the same answer whichever way round you write them. One does not:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
yesterday = {"reset", "timeout", "crc"}
today = {"timeout", "crc", "interrupt"}
print((today & yesterday) == (yesterday & today))
print((today | yesterday) == (yesterday | today))
print((today - yesterday) == (yesterday - today))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
True
True
False

Intersection and union are symmetric. "In both" and "in either" are questions about the pair, so the order of the operands cannot matter.

Difference is not. "In this one and not that one" names a specific side, so swapping asks a genuinely different question.

Symmetric difference is symmetric too — the name says so, and "in one but not both" does not single out a side.

That is a rule you can derive rather than memorise: ask whether the English question mentions a particular set. If it does, the operation has a direction.

8. The Symbols, Collected

Now that each has arrived with a question attached:

QuestionOperatorName
In A but not BA - Bdifference
In bothA & Bintersection
In eitherA | Bunion
In one but not bothA ^ Bsymmetric difference

Every one returns a new set and leaves both operands alone. And of the four, only difference has a direction — Section 7 proved that with the other three giving the same answer either way round.

9. Operators and Methods

Each operation also has a method form:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
yesterday = {"reset", "timeout", "crc"}
today = {"timeout", "crc", "interrupt"}
print(sorted(today.difference(yesterday)))
print(sorted(today.intersection(yesterday)))
print(sorted(today.union(yesterday)))
print(sorted(today.symmetric_difference(yesterday)))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['interrupt']
['crc', 'timeout']
['crc', 'interrupt', 'reset', 'timeout']
['interrupt', 'reset']

Identical results. The method names also make the direction explicit — today.difference(yesterday) reads as "today's, less yesterday's", which some people find harder to get backwards than today - yesterday.

There is one real difference between the two forms. Operators require sets on both sides:

Azvya Education Pvt. Ltd.VLSI Mentor
BROKEN ON PURPOSE
print({"a", "b"} - ["a"])
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
TypeError: unsupported operand type(s) for -: 'set' and 'list'
Azvya Education Pvt. Ltd.VLSI Mentor
BROKEN ON PURPOSE
print({"a"} | ["b"])
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
TypeError: unsupported operand type(s) for |: 'set' and 'list'

Methods accept any iterable:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
today = {"timeout", "crc", "interrupt"}
print(sorted(today.difference(["timeout"])))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['crc', 'interrupt']

A list on the right, and it worked. That is genuinely useful when the other collection arrived as a list and you do not want to convert it first.

Operations chain, since each produces a set:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
yesterday = {"reset", "timeout", "crc"}
today = {"timeout", "crc", "interrupt"}
print(sorted((today | yesterday) - {"crc"}))
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['interrupt', 'reset', 'timeout']

Everything involved in either run, except crc.

10. Predict, Run, Observe

Predict every line before reading on. Two of these are the direction trap.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
a = {"x", "y", "z"}
b = {"y", "z", "w"}
print(sorted(a - b))
print(sorted(b - a))
print(sorted(a & b))
print(len(a | b))
print(sorted(a ^ b))
print((a - b) == (b - a))
print((a & b) == (b & a))
print(len(a), len(b))

The verified output:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
['x']
['w']
['y', 'z']
4
['w', 'x']
False
True
3 3

a - b is ['x'] and b - a is ['w'] — both single elements, completely different meanings. That is Section 3.

a & b is the two shared elements. len(a | b) is 4, not 6: y and z are counted once.

a ^ b is ['w', 'x'] — exactly the two difference results combined, the elements that are in one set only.

The two booleans confirm Section 7: difference is directional, intersection is not.

And the last line shows 3 3 — after five operations, both originals are untouched.

11. Exercises

Exercise 1 — the four questions. Given:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
yesterday = {"reset", "crc", "timeout"}
today = {"crc", "interrupt"}

Without running Python:

  1. Which expression gives the newly failing tests?
  2. Which gives the tests that were fixed?
  3. Which gives the failures common to both runs?
  4. Predict the number of elements in each of those three results.
  5. Run the code and verify all three with sorted() and ==.

Exercise 2 — predict. For p = {1, 2, 3} and q = {3, 4}, give each result, then verify: (a) p - q (b) q - p (c) p & q (d) p | q (e) p ^ q (f) len(p | q) (g) len(p & q)

Exercise 3 — name the question. For each expression, write the English question it answers for two sets of failing tests: (a) today & yesterday (b) yesterday - today (c) today | yesterday (d) today ^ yesterday

Exercise 4 — the backwards report. A colleague's script reports new failures using yesterday - today. Explain in three sentences what it actually reports, why no error occurs, and what a reviewer would wrongly conclude.

Exercise 5 — symmetric or not. Without running anything, say which of these are True and explain the odd one out in two sentences: (a) (a | b) == (b | a) (b) (a & b) == (b & a) (c) (a - b) == (b - a) (d) (a ^ b) == (b ^ a)

Exercise 6 — untouched. Explain in two sentences why c = a - b leaves a unchanged, and name the chapter whose methods behave the opposite way.

Exercise 7 — operator or method. For each, say which form you must or would use and why: (a) both collections are sets, and you want everything in either (b) yesterday is a set and today_list is a list, and you want what is new (c) you want a chained expression removing one name from a union

Exercise 8 — read the error. Run {"a"} - ["a"], write down the exact message, and give two different ways to fix it.

Exercise 9 — build the review. Using the data from Exercise 1, write the four lines a review script would print, each labelled, each using sorted() so the report is reproducible. Say in one sentence why sorted() matters for a report specifically.

12. Summary

  • Learn the questions, then the symbols. Four operations answer four plain questions about two groups.
  • A - B is difference: in A, not in B. It is directional — today - yesterday is what broke, yesterday - today is what got fixed, and nothing in the output distinguishes them.
  • A & B is intersection: in both.
  • A | B is union: in either, each value once. It is not list concatenation — duplicates collapse and there is no order.
  • A ^ B is symmetric difference: in one but not both — everything that changed.
  • Intersection, union and symmetric difference are symmetric; difference is not. If the English question names a particular set, the operation has a direction.
  • Every operation returns a new set and leaves both operands untouched, unlike the in-place methods of Chapter 7.3.
  • Methods match the operators — difference, intersection, union, symmetric_difference — and accept any iterable, while the operators require sets on both sides.
  • Check results with sorted(), len() or == against an expected set, never by printing the set itself.

The next chapter asks about the relationship between two sets rather than computing a third.

Where this fits

Part of the Python curriculum.