Python Difference
Table of Contents + −
In the last lesson you learned Intersection. That gives you the items two sets share. Now we flip the question around. Sometimes you do not care what they have in common. You want the items that are in one set but missing from the other. That is what difference is for.
🤔 Why Do We Need Difference?
Say Alex has a shopping cart and Riya has one too. You want to know which items are in Alex’s cart that Riya did not add. If you do this by hand, you loop over Alex’s items and check each one against Riya’s list. That is slow to write. It is also easy to get wrong.
Difference solves this in one step. It gives you the items in the first set that are NOT in the second set.
So why does this matter so often?
- A lot of real work is just comparing two lists. Who is here, who is missing, what changed.
- Difference answers “what is in this group but not that one” without you writing a loop.
- Sets are also fast at this. Checking if an item exists in a set is quick, so even big lists compare in no time.
🧩 What Is a Set Difference?
Think of two groups of friends. One group went to the party. Another group went to the movie. The difference “party minus movie” is the friends who went to the party but not the movie.
So a - b means this. Take everything in a. Then drop anything that also appears in b. What is left is the answer.
You can write it in two ways. There is the difference() method. There is also the - operator. They do the same thing.
Here we make two sets and find the items in the first one but not the second.
a = {1, 2, 3, 4}b = {3, 4, 5, 6}
print(a.difference(b))print(a - b)Output
{1, 2}{1, 2}Both lines print the same thing. The numbers 1 and 2 are in a. Neither of them is in b, so they stay in the answer. The numbers 3 and 4 appear in both, so they get dropped.
So which form should you use? It is mostly about reading.
- The
-operator is short and quick to type. Good for a fast one-liner. - The
difference()method reads more like a sentence, which is nice in longer code. - One small extra:
a.difference(b, c)lets you pass more than one set at once. The-only works between two sets at a time, so you would writea - b - c.
↔️ Order Matters
This is the part people get wrong most often. With difference, a - b is NOT the same as b - a. The order changes the answer.
Here we run the difference both ways so you can see they differ.
a = {1, 2, 3, 4}b = {3, 4, 5, 6}
print(a - b)print(b - a)Output
{1, 2}{5, 6}See the difference? Let us read each line out loud.
a - basks “what is inabut notb”, so you get1and2.b - aasks “what is inbbut nota”, so you get5and6.- Same two sets, two different answers. It all comes down to which one comes first.
Tip
Read a - b out loud as “a, take away b”. Whatever you start with is what you keep from. The second set is only the list of things to remove.
🆕 Difference Makes a Brand-New Set
One thing to keep clear. Plain difference does not touch your original sets. It builds a fresh set and hands that back. Your two starting sets stay exactly as they were.
Here we take a difference and then print the originals to check they did not change.
a = {1, 2, 3, 4}b = {3, 4, 5, 6}
result = a - b
print("result:", result)print("a is still:", a)print("b is still:", b)Output
result: {1, 2}a is still: {1, 2, 3, 4}b is still: {3, 4, 5, 6}See that? The result is the new set with 1 and 2. But a and b are untouched. So you can keep comparing them as much as you like, and nothing gets lost.
✏️ Changing the Original: difference_update
Now and then you do not want a new set. You want to edit the original set in place and throw away the common items right there. That is what difference_update() does. There is a short operator form too: -=.
Here we strip out the shared items straight from a instead of making a copy.
a = {1, 2, 3, 4}b = {3, 4, 5, 6}
a.difference_update(b)print(a)
# the -= operator does the same thingc = {1, 2, 3, 4}c -= bprint(c)Output
{1, 2}{1, 2}So what happened here?
a.difference_update(b)removed every item ofathat was also inb. It changedaitself, it did not return a new set.c -= bis the same idea with the operator. After it runs,cis the trimmed set.- The second set,
b, is never changed by either form. Only the left side gets edited.
Caution
difference_update() returns None, not a set. So do not write a = a.difference_update(b). That would set a to None and lose your data. Just call it on its own line, or use a = a - b if you want a fresh set instead.
🛒 A Real Example: Two Shopping Carts
Let us go back to Alex and Riya. Each one has a cart of items. We want the items only Alex has.
Here we compare the two carts and find what is unique to each shopper.
alex_cart = {"milk", "bread", "eggs", "coffee"}riya_cart = {"bread", "coffee", "butter"}
only_alex = alex_cart - riya_cartonly_riya = riya_cart - alex_cart
print("Only in Alex's cart:", only_alex)print("Only in Riya's cart:", only_riya)Output
Only in Alex's cart: {'milk', 'eggs'}Only in Riya's cart: {'butter'}alex_cart - riya_cart keeps the items Alex has that Riya does not, so milk and eggs. The other way round, riya_cart - alex_cart, gives butter. That is the one thing Riya added that Alex did not.
Note
Sets have no order, so your output might list the items in a different position, like {'eggs', 'milk'}. That is fine. A set does not promise an order. It only promises which items are inside.
📧 A Second Example: Who Has Not Replied Yet
Here is another spot where difference saves you. Say Arjun sent an event invite to a group of people. Some have replied, some have not. He wants the list of people he still needs to chase.
So he has two sets. One is everyone he invited. One is everyone who replied. The people he still needs to follow up with is “invited, take away replied”.
Here we find the invitees who have not answered yet.
invited = {"Alex", "Riya", "Arjun", "Sara", "Omar"}replied = {"Riya", "Omar"}
not_replied = invited - repliedprint("Still waiting on:", not_replied)Output
Still waiting on: {'Alex', 'Arjun', 'Sara'}See how clean that is? No loop, no checking each name by hand.
invited - repliedkeeps everyone ininvitedwho is not inreplied.RiyaandOmaralready replied, so they drop out.- What is left,
Alex,Arjun, andSara, is exactly the chase list.
The same shape works for many things. Students who missed an exam is “all students minus students who showed up”. Files removed between two versions is “old file list minus new file list”. Once you see the pattern, you will spot it everywhere.
🔀 Symmetric Difference
There is a cousin of difference worth knowing. Plain difference is one-directional. Symmetric difference is two-directional. It gives you the items that are in one set or the other, but NOT in both.
So it is like saying “the things that are unique to either side”. You use the ^ operator, or the symmetric_difference() method.
Here we find every item that only one of the two carts has.
alex_cart = {"milk", "bread", "eggs", "coffee"}riya_cart = {"bread", "coffee", "butter"}
print(alex_cart ^ riya_cart)print(alex_cart.symmetric_difference(riya_cart))Output
{'milk', 'eggs', 'butter'}{'milk', 'eggs', 'butter'}The shared items, bread and coffee, are gone. What stays is milk and eggs from Alex, plus butter from Riya. It is the same as combining alex_cart - riya_cart with riya_cart - alex_cart.
So how is this different from plain difference? Here is the key bit.
- Plain difference
a - bonly keeps froma. It throws away the extra items inb. - Symmetric difference
a ^ bkeeps the unique items from both sides. - And because both sides are treated equally, order does not matter.
a ^ bis always the same asb ^ a.
There is an in-place form here too, just like before. symmetric_difference_update() and the ^= operator edit the original set instead of making a new one.
Here we update Alex’s cart in place to hold only the items the two carts do not share.
alex_cart = {"milk", "bread", "eggs", "coffee"}riya_cart = {"bread", "coffee", "butter"}
alex_cart.symmetric_difference_update(riya_cart)print(alex_cart)Output
{'milk', 'eggs', 'butter'}After this, alex_cart itself holds the unique items. The ^= operator would do the same thing in shorter form.
Here is a quick way to keep the operators straight.
| Operation | Operator | Method | What you get |
|---|---|---|---|
| Difference | a - b | a.difference(b) | In a but not b, new set |
| Difference in place | a -= b | a.difference_update(b) | Edits a itself, returns nothing |
| Symmetric difference | a ^ b | a.symmetric_difference(b) | In one set or the other, not both |
| Symmetric difference in place | a ^= b | a.symmetric_difference_update(b) | Edits a itself, returns nothing |
⚠️ Common Mistakes
A few things are easy to get wrong, so watch for these.
- Mixing up the order. Remember
a - bkeeps froma. If you got the wrong items, you probably need to flip the two sets. - Expecting difference to be two-directional. Plain difference only removes. It never adds the extra items from the second set. If you want both unique sides, that is symmetric difference.
- Confusing
-with^. The-is one-directional and order matters. The^is two-directional and order does not matter. - Using
-between a set and a list. The-operator only works set-to-set. If the other side is a list, use thedifference()method, which happily takes a list. - Saving the result of an update method. The in-place forms return
None, so do not assign their result back to your variable.
Here is the order mistake in code.
prices_today = {"apple", "banana"}prices_yesterday = {"banana", "cherry"}
# ❌ Avoid: wrong order, this gives items new yesterday, not todayprint(prices_yesterday - prices_today)
# ✅ Good: items that are new todayprint(prices_today - prices_yesterday)Output
{'cherry'}{'apple'}And here is the set-to-list mistake. The - operator cannot subtract a list, but the method can.
have = {"milk", "bread", "eggs"}need_to_skip = ["bread"]
# ❌ Avoid: the - operator does not accept a list# print(have - need_to_skip) # this would raise a TypeError
# ✅ Good: the difference() method takes a list just fineprint(have.difference(need_to_skip))Output
{'milk', 'eggs'}✅ Best Practices
- Pick the form that reads well. The
-and^operators are short and clear for quick work. Thedifference()andsymmetric_difference()methods read more like a sentence, which helps in longer code. - Say the goal in words first. “Items in this one but not that one” means difference. “Items unique to either” means symmetric difference. Then pick the tool.
- When order matters, name your sets clearly. Good names like
only_alexmakealex_cart - riya_carteasy to read and hard to get backwards. - Reach for
difference()over-when the other side might be a list or some other collection, not a set. The method is more forgiving there. - Use the update forms only when you really mean to change the original. If anything else still reads from that set, make a new set with
-instead so you do not surprise it.
🧩 What You’ve Learned
✅ Difference gives you the items in the first set that are NOT in the second set.
✅ You can use the difference() method or the - operator. They do the same thing, and both build a brand-new set, leaving your originals unchanged.
✅ Order matters: a - b is not the same as b - a, because you always keep from the first set.
✅ difference_update() and -= edit the original set in place instead of making a new one, and they return nothing.
✅ Symmetric difference, the ^ operator or symmetric_difference() method, gives items in one set or the other but not both.
✅ Symmetric difference treats both sides equally, so order does not matter there.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What does a - b return?
Why: Difference keeps the items from the first set and removes any that also appear in the second set.
- 2
Given a = {1, 2, 3} and b = {2, 3, 4}, what does b - a give?
Why: b - a keeps items from b that are not in a, and only 4 is in b but not a.
- 3
Which operator gives items that are in one set or the other but not both?
Why: The ^ operator (symmetric_difference) returns items unique to either set, dropping the shared ones.
- 4
What does a.difference_update(b) do?
Why: difference_update() changes the original set a in place, removing items also in b, and returns None rather than a new set.
🚀 What’s Next?
You now know how to pull sets apart and compare them. Next we will round up the handy set methods you will reach for again and again, like adding, removing, and copying items.