Python Intersection

In the last lesson you learned Union. There you joined two sets to get everything from both. Now we turn that idea around. Sometimes you do not want everything. You only want the items that sit in both sets at the same time. That overlap has a name. Finding it is what this lesson is about.

🤔 Why Intersection?

Picture a coffee shop running a poll. One list holds the people who like tea. Another holds the people who like coffee. The owner wants to send a special offer to the people who like both.

So here is the problem you keep hitting:

  • You have two groups of items, and you only want the ones that show up in each group.
  • Doing it by hand means walking name by name through one list and looking each name up in the other. That gets slow.
  • And it is easy to slip up. You miss a name, or you count one twice, right?

The fix is one clean operation. Intersection takes two sets and gives you back only the items that appear in both of them. Nothing else. No loops, no manual checking.

🧩 What Is Intersection?

Intersection means the shared part. You take two sets, you look at where they overlap, then you keep only that overlap.

Think of two circles that cross each other, like in a Venn diagram. The little slice in the middle, where the circles sit on top of each other, is the intersection. An item only makes it into the result if it lives in the first set and in the second set. If it is in just one of them, it is out.

Python gives you two ways to do this:

  • The intersection() method, like a.intersection(b).
  • The & operator, like a & b.

Both do the exact same job. So pick whichever reads better to you. We will use both all through this lesson so you get comfortable with each one.

🍵 A Real Example

Let’s build those two groups from the poll. One set of tea lovers, one set of coffee lovers. We want the people who like both.

tea = {"Alex", "Riya", "Arjun", "Sara"}
coffee = {"Riya", "Sara", "John"}
both = tea.intersection(coffee)
print(both)

Read it line by line:

  • tea holds four people who like tea.
  • coffee holds three people who like coffee.
  • tea.intersection(coffee) looks for the people who are in both sets and collects them.
  • print(both) shows the result.

Only Riya and Sara appear in both groups. So that is what you get back.

Output

{'Riya', 'Sara'}

See why? Alex and Arjun only like tea. John only likes coffee. So none of them make the cut. And remember, a set does not keep any order. So your result might print as {'Sara', 'Riya'} instead. The items are the same either way.

🔗 The & Operator

The & symbol does the same thing. It is just shorter. You put one set on each side of it.

This is the same poll, written with &:

tea = {"Alex", "Riya", "Arjun", "Sara"}
coffee = {"Riya", "Sara", "John"}
both = tea & coffee
print(both)

The line tea & coffee reads almost like plain English. “Tea and coffee” means the people in both. It gives you the very same answer.

Output

{'Riya', 'Sara'}

So when do you use which? Here is the simple way to choose:

  • Reach for & when the line is short and you want it quick.
  • Reach for intersection() when spelling out the action makes longer code easier to read.

They behave the same. So it really comes down to taste. There is one small difference we will see later, around lists, but for set-to-set work they match exactly.

👥 Another Example: Friends Both People Follow

Here is a second real one, so the idea sticks. Think about a social app like Instagram. Alex follows some accounts. Riya follows some accounts. You want to know the accounts they both follow, maybe to suggest a group chat.

alex_follows = {"nasa", "natgeo", "bbc", "espn"}
riya_follows = {"natgeo", "espn", "vogue"}
common = alex_follows & riya_follows
print(common)

We line up who each person follows. alex_follows & riya_follows keeps only the accounts that show up on both lists. Both of them follow natgeo and espn. So those two come back.

Output

{'natgeo', 'espn'}

This is exactly how “you both follow” or “mutual” features work under the hood. Same trick works for the skills two job candidates share, or the products sitting in two shopping carts at once. Anytime you ask “what do these two have in common?”, that is intersection.

🔢 Intersection of More Than Two Sets

Real life is not always just two groups, right? Say three friends are planning a trip, and you want the dates that all three of them are free. That means an item has to appear in every single set, not just two.

Good news. Both forms scale up. You can chain &, or pass extra sets to intersection().

alex = {"Fri", "Sat", "Sun"}
riya = {"Sat", "Sun", "Mon"}
arjun = {"Sun", "Mon", "Tue"}
# chain the & operator
free_all = alex & riya & arjun
print(free_all)
# same thing with the method, extra sets as arguments
free_all = alex.intersection(riya, arjun)
print(free_all)

Walk through it:

  • alex & riya & arjun keeps only the days found in all three sets.
  • alex.intersection(riya, arjun) does the very same job. The method takes as many sets as you like, separated by commas.
  • The only day all three are free is Sun.

Output

{'Sun'}

So the rule grows naturally. With two sets, an item must be in both. With three sets, it must be in all three. Add more sets, and the result only gets smaller, never bigger, because each new set is one more test the item has to pass.

🔁 Changing the Original: intersection_update() and &=

Everything so far built a brand new set and left your originals alone. But sometimes you actually want to shrink the original set down to just the shared items. That is what the in-place versions do.

There are two of them, and they match the two forms you already know:

  • intersection_update() is the in-place method.
  • &= is the in-place operator.

Here tea itself gets trimmed down to only the shared people:

tea = {"Alex", "Riya", "Arjun", "Sara"}
coffee = {"Riya", "Sara", "John"}
tea.intersection_update(coffee)
print(tea)

See the difference? We did not store the answer in a new variable. We changed tea directly. After this line, tea holds only the people who were in both sets.

Output

{'Riya', 'Sara'}

The &= operator is the short form of the same idea:

tea = {"Alex", "Riya", "Arjun", "Sara"}
coffee = {"Riya", "Sara", "John"}
tea &= coffee
print(tea)

tea &= coffee means “set tea to tea & coffee”. So tea is updated in place to the shared items.

Output

{'Riya', 'Sara'}

So now you have a clear choice:

  • Use & or intersection() when you want a new set and want to keep the originals.
  • Use &= or intersection_update() when you are happy to overwrite the first set with the shared items.

🚫 No Overlap At All: The Empty Result

Now, what if two sets share nothing? Like tea lovers and a list of people who only drink water. There is no overlap. So what comes back?

You get an empty set. In Python that prints as set(), not {}. The {} shape is reserved for an empty dictionary, so Python writes an empty set the long way.

tea = {"Alex", "Riya", "Sara"}
water = {"Maya", "John"}
both = tea & water
print(both)

Nobody is in both groups. So the intersection holds nothing.

Output

set()

How do you check for that in code? An empty set is “falsy”, which means Python treats it like False in an if. So you can test it plainly:

both = tea & water
if both:
print("They share:", both)
else:
print("Nothing in common")

if both: runs the first branch only when the set has something in it. An empty set skips to the else. So here it prints the no-overlap message.

Output

Nothing in common

🧪 isdisjoint(): Asking “Do They Share Anything?”

Sometimes you do not care what two sets share. You only want a yes or no answer to “do they overlap at all?”. Building the whole intersection just to check if it is empty works, but there is a cleaner tool made for exactly this.

That tool is isdisjoint(). Two sets are “disjoint” when they share zero items. So a.isdisjoint(b) returns True if they have nothing in common, and False if they share even one item.

tea = {"Alex", "Riya", "Sara"}
water = {"Maya", "John"}
coffee = {"Riya", "John"}
print(tea.isdisjoint(water)) # no shared people
print(tea.isdisjoint(coffee)) # Riya is in both

Read it like this:

  • tea and water share nobody, so they are disjoint. That gives True.
  • tea and coffee both contain Riya, so they are not disjoint. That gives False.

Output

True
False

So how does this tie back to intersection? Like this:

  • a.isdisjoint(b) being True means the same as a & b giving you set().
  • They are two ways of asking the same question.

Why prefer isdisjoint() when you just need the yes/no? Because it can stop early. The moment it finds one shared item, it answers False and stops looking. It does not have to collect the whole overlap first. So it is a little faster and reads clearer when all you want is “do these two touch or not?”.

🆕 Intersection Returns a New Set

Here is something worth pausing on, just to be sure it is solid. Plain intersection, with & or intersection(), does not change either of your original sets. It builds a brand new set with the shared items in it and hands that back to you.

This little check proves it. We make the intersection, then we print the original sets again:

tea = {"Alex", "Riya", "Sara"}
coffee = {"Riya", "Sara", "John"}
both = tea & coffee
print(both)
print(tea)
print(coffee)

The result lands in both. Meanwhile tea and coffee stay exactly as they were.

Output

{'Riya', 'Sara'}
{'Alex', 'Riya', 'Sara'}
{'Riya', 'Sara', 'John'}

So you can safely reuse tea and coffee afterwards. The intersection is a fresh set, separate from both inputs. Just remember the in-place versions, &= and intersection_update(), are the exception. Those do change the first set on purpose.

⚠️ Common Mistakes

A few small things trip people up at first. Watch for these.

  • Expecting plain intersection to change the originals. & and intersection() give you a new set. They leave your two starting sets alone. If you want the result, store it in a variable. If you actually want to change the original, that is what &= and intersection_update() are for.
# ❌ Avoid: throwing the result away, then wondering where it went
tea.intersection(coffee)
print(tea) # still the full tea set, nothing "happened"
# ✅ Good: catch the new set in a variable
both = tea.intersection(coffee)
print(both)
  • Mixing up & and |. This is the big one. & is intersection, the shared part. | is union, everything from both. They look similar but do opposite things. So pause and check which symbol you typed.
a = {1, 2, 3}
b = {2, 3, 4}
print(a & b) # ✅ intersection -> {2, 3}, only the shared items
print(a | b) # this is union -> {1, 2, 3, 4}, everything
  • Expecting the result in some order. A set has no order. So do not assume the shared items print sorted or in the order you added them. If you need order, sort the result with sorted(both), which hands you back a list.

  • Using & between a set and a list. The & operator needs sets on both sides. If one side is a list, Python crashes with a TypeError. The intersection() method is more relaxed here. It happily accepts a list as its argument and treats it as a set for you.

tea = {"Alex", "Riya", "Sara"}
guests = ["Riya", "John"]
# ❌ Avoid: & demands a set on both sides
# print(tea & guests) # TypeError
# ✅ Good: the method accepts a list argument
print(tea.intersection(guests)) # {'Riya'}

✅ Best Practices

Keep these small habits and intersection stays easy:

  • Save the result in a variable when you use & or intersection(). They return a new set instead of changing the originals.
  • Reach for &= or intersection_update() only when you really mean to overwrite the first set. Otherwise keep the originals safe.
  • When you just need a yes/no on “do these two share anything?”, use isdisjoint(). It is clearer and can stop early.
  • Test an empty result with a plain if both:. An empty set is falsy, so this reads cleanly.
  • If your data lives in lists, either convert them to sets first, or use intersection(), which accepts a list argument directly.
  • Remember a set has no order. So sort with sorted() if you need the items in a fixed sequence.

🧩 What You’ve Learned

  • ✅ Intersection gives you only the items that appear in both sets, and you find it with intersection() or the & operator.
  • ✅ You can intersect more than two sets with a & b & c or a.intersection(b, c), keeping only items found in all of them.
  • intersection_update() and &= change the original set in place instead of returning a new one.
  • ✅ When two sets share nothing, you get an empty set, which prints as set(), and isdisjoint() returns True for that case.
  • ✅ Plain intersection returns a new set and leaves your originals unchanged, and a set has no order, so the result can print in any sequence.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What does set intersection give you back?

    Why: Intersection keeps only the overlap, the items found in both sets at the same time.

  2. 2

    What is `a.intersection(b, c)` for a = {1, 2, 3}, b = {2, 3, 4}, c = {3, 4, 5}?

    Why: An item must appear in all three sets. Only 3 is in a, b, and c, so the result is {3}.

  3. 3

    Two sets share no items. What does `a.isdisjoint(b)` return, and what does `a & b` give?

    Why: No shared items means the sets are disjoint, so isdisjoint() is True and the intersection is the empty set set().

  4. 4

    After `tea.intersection_update(coffee)`, what happens to `tea`?

    Why: intersection_update() changes the set in place, so tea is trimmed down to only the items shared with coffee.

🚀 What’s Next?

You can now find what two sets share, in every form. Next you will learn the flip side. You will find the items that are in one set but not in the other.

Difference

Share & Connect