Sets & Choosing a Collection

The Course
•
January 7, 2026
•
6 min read

A set is an unordered collection with no duplicates. Adding something twice changes nothing.

Duplicates disappear Python
tags = {"python", "beginner", "python", "tutorial"}
print(tags)
print(len(tags))

# The usual way to make one: from another collection.
visitors = ["ada", "alan", "ada", "grace", "alan"]
unique = set(visitors)
print(unique)
print(len(unique), "unique visitors out of", len(visitors))
Empty braces make a dictionary

{} is an empty dictionary, not an empty set — dictionaries got the syntax first. For an empty set, write set().

Membership is the superpower

Checking x in collection on a list means looking at every item. On a set it is effectively instant, however large the set grows — the same mechanism that makes dictionary lookups fast.

A list scan versus a set lookup Python
import time

big_list = list(range(200_000))
big_set = set(big_list)
target = 199_999

start = time.perf_counter()
target in big_list
list_time = time.perf_counter() - start

start = time.perf_counter()
target in big_set
set_time = time.perf_counter() - start

print(f"list: {list_time * 1000:.3f} ms")
print(f"set:  {set_time * 1000:.3f} ms")

If your code says if item in some_list: inside a loop, converting that list to a set once beforehand is often the single biggest speed-up available to you.

Set arithmetic

Sets answer questions about groups: what is in both, what is in only one, what is in either.

Comparing two groups Python
morning = {"ada", "alan", "grace"}
evening = {"grace", "katherine", "alan"}

print(morning & evening)     # intersection - in both
print(morning | evening)     # union - in either
print(morning - evening)     # difference - morning only
print(morning ^ evening)     # symmetric difference - in exactly one

print(morning.isdisjoint({"linus"}))
print({"ada"} <= morning)    # is it a subset?

Each operator has a spelled-out method too — .intersection(), .union(), .difference() — which reads better in code that others will maintain.

Changing a set

add, discard, remove Python
langs = {"python"}

langs.add("rust")
langs.add("python")        # already there, no effect
print(langs)

langs.discard("go")        # missing is fine
langs.remove("rust")       # missing raises KeyError
print(langs)

Sets are unordered, so there is no indexing: langs[0] is an error. If you need order, sort into a list when you need it: sorted(langs).

Choosing a collection

You needUseWhy
An ordered, changing sequencelistIndexing, slicing, appending
A fixed record of related valuestupleImmutable, unpackable, safe as a dict key
Lookup by name or iddictInstant access by key
Uniqueness or fast membershipsetNo duplicates, instant in

Most bugs of the “this is slow” or “why is it duplicated” kind trace back to this table.

Before you write your own

1. Predict. Six visits, but on how many different days?

What will this print? Python
visits = ["mon", "tue", "mon", "wed", "tue", "mon"]
days = set(visits)

print(len(visits), len(days))
print("thu" in days)
print(sorted(days))
print(sorted({"a", "b", "c"} - {"b"}))
Check your prediction
6 3
False
['mon', 'tue', 'wed']
['a', 'c']

A set can’t hold duplicates, so the three "mon"s become one. Sets have no order of their own, which is why every line that shows a set’s contents goes through sorted first.

2. Fix. This should collect the unique tags and print ['python', 'tips'].

Not a set Python
tags = {}
for tag in ["python", "tips", "python"]:
    tags.add(tag)
print(sorted(tags))
Check your fix
tags = set()
for tag in ["python", "tips", "python"]:
    tags.add(tag)
print(sorted(tags))
['python', 'tips']

{} is an empty dictionary, and dictionaries have no add. The error message — 'dict' object has no attribute 'add' — names the real type, which is the clue.

3. Choose. No code for this one. For each job, which of list, tuple, dictionary or set would you reach for, and why?

  1. The steps of a recipe, in order.
  2. Looking up a customer’s email address by their username.
  3. Remembering which words you’ve already seen in a long text.
  4. A colour, as red, green and blue values.
Check your choices
  1. List — order matters, and you might add a step.
  2. Dictionary — you’re looking something up by a name.
  3. Set — the only question is “have I seen this?”, and in on a set is instant.
  4. Tuple — a fixed number of values that together describe one thing.

If you picked differently and can say why, that’s worth more than matching. A list of words would work for (3) — it would just get slow as it grew.

Exercise

Compare two reading lists

Two people list the books they have read. Print how many books they have read between them, which they have both read, and which only Ada has read — each alphabetically. Your output should be:

Between them: 5
Both read:    ['Solaris', 'Ubik']
Ada only:     ['Dune', 'Piranesi']
ada = ["Dune", "Piranesi", "Solaris", "Ubik"]
alan = ["Solaris", "Ubik", "Neuromancer"]

# Your code here
Hint 1: the idea

All three questions are about groups: in either list, in both, in Ada’s only. Those are exactly the set operators above — once each list is a set.

Hint 2: a first step

Convert once: ada_set = set(ada) and alan_set = set(alan). Then len(ada_set | alan_set) answers the first question. sorted() turns a set into an alphabetical list for printing.

Show one solution
ada = ["Dune", "Piranesi", "Solaris", "Ubik"]
alan = ["Solaris", "Ubik", "Neuromancer"]

ada_set = set(ada)
alan_set = set(alan)

print("Between them:", len(ada_set | alan_set))
print("Both read:   ", sorted(ada_set & alan_set))
print("Ada only:    ", sorted(ada_set - alan_set))

Convert to sets once, then let the operators do the work. The same three answers written with loops and if x in y would run to fifteen lines and be slower.

Day 3 is done

You now have all four core containers. Almost every Python program is some arrangement of lists of dictionaries, dictionaries of lists, and sets used to answer “have I seen this before?”.

Tomorrow you learn to name behaviour, not just data.

What you learned

  • Sets hold unique, unordered items; set() makes an empty one.
  • in is fast on sets and dictionaries, slow on lists.
  • &, |, -, ^ compare groups.
  • add, discard (safe) and remove (strict) change a set.
  • Pick the container by the question you need to ask of it.
Last updated on January 7, 2026

Was this article helpful?

Your response is saved on this device.