Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

Set Union, Intersection, Difference

Learn to manipulate Python sets with union, intersection, and difference operations in this hands-on tutorial. Step-by-step walkthrough with troubleshooting.

Focus: manipulate sets with union, intersection, difference

Sponsored

You've mastered lists and dictionaries, but what happens when you need to work with unique elements and perform mathematical set operations like finding common items or differences between groups? Without union, intersection, and difference, you'd be stuck writing slow loops and complex condition checks. Python's built-in set type gives you these operations at blazing speed, turning common data problems into elegant one-liners.

The problem this lesson solves

Imagine you're building a social network feature: you need to find mutual friends (common elements) between two users, suggest new friends who are in one network but not the other, or combine two friend lists without duplicates. Without set operations, you'd write something like:

list1 = ["alice", "bob", "charlie"]
list2 = ["bob", "dave", "eve"]

# Manual union (no duplicates)
combined = list1.copy()
for item in list2:
    if item not in combined:
        combined.append(item)

# Manual intersection
common = []
for item in list1:
    if item in list2:
        common.append(item)

# Manual difference
unique_to_list1 = []
for item in list1:
    if item not in list2:
        unique_to_list1.append(item)

This code is verbose, error-prone, and slow (O(nm) for intersection). Worse, it's hard to read and maintain. Python sets solve all three problems with mathematically precise, highly optimized* operations.

Core concept / mental model

Think of a set as a bag of unique items, like a guest list where nobody's name appears twice. The three core operations are:

  • Union: Pour both bags together, keep only one copy of each item. Result contains all items from both sets.
  • Intersection: Find items that appear in both bags simultaneously. Result contains only the shared items.
  • Difference: Take items from the first bag that are not in the second bag. Result contains items unique to the first set.

Formal definitions (for clarity)

Operation Symbol Py method / operator Result contains...
Union A ∪ B A.union(B) or A | B All unique elements from A and B
Intersection A ∩ B A.intersection(B) or A & B Elements present in both A and B
Difference A – B A.difference(B) or A – B Elements in A but not in B

Pro tip: Sets are unordered — don't rely on insertion order. Use sets when uniqueness and membership tests matter; use lists when order matters.

How it works step by step

  1. Create sets from lists or directly with set() or curly braces: my_set = {1, 2, 3}. Remember: empty braces {} create a dict, not a set. Use set() for an empty set.

  2. Call the method or use the operator: set1.union(set2) or set1 | set2. Both work identically. Methods accept any iterable; operators require both operands to be sets.

  3. Capture the result: These operations return a new set — they do not modify the original sets. If you want to modify a set in place, use update variants: union_update() (or |=), intersection_update() (&=), difference_update() (-=).

In-place vs. copy

Operation Returns new set Modifies in place
Union A.union(B), A | B A.update(B), A |= B
Intersection A.intersection(B), A & B A.intersection_update(B), A &= B
Difference A.difference(B), A – B A.difference_update(B), A -= B

Pro tip: Use the operator syntax (|, &, -) for readability; use methods when you need to pass a list or tuple as the other argument.

Hands-on walkthrough

Let's apply this to a realistic scenario: we have two guest lists for a conference — VIPs and workshop attendees. We'll find: - All guests combined (union). - Guests who are both VIPs and attending workshops (intersection). - VIPs who are not attending any workshop (difference).

# Example 1: Basic set operations
vips = {"Alice", "Bob", "Charlie", "Diana"}
workshop_attendees = {"Bob", "Diana", "Eve", "Frank"}

# Union: all unique guests
all_guests = vips | workshop_attendees
print(f"All guests: {all_guests}")
# Output (order may vary): All guests: {'Alice', 'Bob', 'Charlie', 'Diana', 'Eve', 'Frank'}

# Intersection: guests doing both
both = vips & workshop_attendees
print(f"Both VIP and workshop: {both}")
# Output (order may vary): Both VIP and workshop: {'Bob', 'Diana'}

# Difference: VIPs skipping workshop
vips_only = vips - workshop_attendees
print(f"VIPs not attending: {vips_only}")
# Output (order may vary): VIPs not attending: {'Alice', 'Charlie'}

# Difference: workshop-only guests
workshop_only = workshop_attendees - vips
print(f"Workshop-only: {workshop_only}")
# Output (order may vary): Workshop-only: {'Eve', 'Frank'}
# Example 2: Using methods with non-set iterables
checked_in = ["Alice", "Bob", "Charlie"]  # list (may contain duplicates?)
registered = {"Bob", "Diana", "Eve"}       # set

# Union: method accepts list
all_attendees = registered.union(checked_in)
print(f"All attendees: {all_attendees}")
# Output (order may vary): All attendees: {'Alice', 'Bob', 'Charlie', 'Diana', 'Eve'}

# Intersection: method accepts list
active_registered = registered.intersection(checked_in)
print(f"Checked in and registered: {active_registered}")
# Output (order may vary): Checked in and registered: {'Bob'}
# Example 3: In-place operations (modify original set)
vips = {"Alice", "Bob", "Charlie"}
early_birds = {"Alice", "Diana"}

# Add early birds to VIPs in place (union update)
vips |= early_birds
print(vips)  # Output: {'Alice', 'Bob', 'Charlie', 'Diana'}

# Remove early birds from VIPs in place (difference update)
vips -= early_birds
print(vips)  # Output: {'Bob', 'Charlie'}

# Keep only those in both (intersection update)
vips &= {"Bob", "Eve"}
print(vips)  # Output: {'Bob'}

Compare options / when to choose what

Scenario Best operation Why
Combine two lists of unique customers union (or |) No duplicates, fast membership
Find items common to both datasets intersection (or &) Single line, O(min(len(a), len(b)))
Find missing values from one list difference (or -) Exact set of exclusions
Combine many sets at once union(*sets) No chaining needed
Need to keep duplicates? Use lists, not sets Sets discard duplicates
Need ordered result? Convert back to list: list(result) Sets are unordered

Pro tip: For symmetric difference (items in A or B but not both), use A ^ B or A.symmetric_difference(B). This is like "exclusive or" for sets.

Troubleshooting & edge cases

  • Empty sets: All operations work fine with empty sets. {1, 2} & set() returns set().
  • Mutable elements: Sets can only contain hashable elements (strings, numbers, tuples). Lists, dicts, or other sets will raise TypeError: unhashable type.
  • Order not guaranteed: Don't rely on insertion order. Use sorted() if you need consistent output: sorted(result).
  • Operator precedence: | and & have lower precedence than comparison operators. Use parentheses: (a | b) & c vs a | b & c (which Python interprets as a | (b & c)).
  • Modifying while iterating: You can't add or remove elements from a set while iterating over it. Create a copy or collect items to add/remove in a separate list.
# Common mistake: Unhashable type
# bad_set = {[1, 2], [3, 4]}  # TypeError: unhashable type: 'list'

# Correct way: use tuples
correct_set = {(1, 2), (3, 4)}

# Modifying during iteration — wrong
my_set = {1, 2, 3}
# for item in my_set:
#     my_set.add(item + 10)  # RuntimeError: Set changed size during iteration

# Correct approach: iterate over a copy
for item in my_set.copy():
    my_set.add(item + 10)
print(my_set)  # Output: {1, 2, 3, 11, 12, 13}

What you learned & what's next

You now know how to: - Explain the core idea behind set union, intersection, and difference as mathematical operations for unique elements. - Apply these operations using both operators (|, &, -) and methods (.union(), .intersection(), .difference()). - Choose between creating new sets vs. modifying in place with update variants. - Avoid common pitfalls like unhashable elements or iteration-modification conflicts.

These operations are fundamental to data cleaning, permission systems, tagging, and any application where you need to compare groups. In the next lesson, you'll build on this foundation by learning set comprehensions — a powerful syntax for creating sets inline, much like list comprehensions but with automatic deduplication.

Practice today: rewrite the manual friend-matching code from the beginning using proper set operations. You'll see how three lines replace twenty.

Practice recap

Try this: create three sets — a = {1, 2, 3, 4}, b = {3, 4, 5, 6}, c = {5, 6, 7, 8}. Compute the union of all three, the intersection of a and c, and the difference of b from a. Then print each result sorted. You'll see how to handle multiple sets in one expression.

Common mistakes

  • Using {} to create an empty set — creates an empty dict instead. Always use set() for an empty set.
  • Assuming sets preserve insertion order — they don't. Use sorted() or switch to lists if order matters.
  • Forgetting operator precedence: a | b & c is parsed as a | (b & c), not (a | b) & c. Add parentheses.
  • Trying to store mutable elements (list, dict, set) inside a set — raises TypeError: unhashable type. Use tuples instead.

Variations

  1. Use frozenset for an immutable, hashable set that can itself be a set element or dictionary key.
  2. For symmetric difference (items in A or B but not both), use A ^ B or A.symmetric_difference(B) — helpful for finding unique disagreements.
  3. Chain multiple operations: (a | b) – (c & d) — but use parentheses for clarity, even when not strictly needed.

Real-world use cases

  • Finding mutual followers between two Twitter accounts by intersecting their follower sets.
  • Cleaning a list of user input tags by converting to a set (removes duplicates) then applying union to merge from multiple sources.
  • Computing which IP addresses are in a whitelist but not in a blacklist using difference, for firewall rules.

Key takeaways

  • Use | for union, & for intersection, - for difference — they're fast and readable.
  • Sets store only unique elements and require all items to be hashable (strings, numbers, tuples).
  • Operators require both operands to be sets; methods accept any iterable as the argument.
  • Use in-place operators (|=, &=, -=) to modify the original set without creating a new one.
  • Sets are unordered — don't rely on insertion order; convert to sorted list if needed.
  • Always use set() for an empty set, never {}.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.