Sets
How many different cities did your customers order from? Which students joined both the cricket team and the coding club? Which skills does a job need that you do not have yet? These are questions about unique values and about what two groups share, and Python's set type answers them in a single line.
In this lesson you will create sets, use them to remove duplicates and to test membership quickly, add and remove items, combine sets with union, intersection and difference, and meet the unchangeable frozenset.
Creating a set
A set is an unordered collection of unique values, written in curly braces. If you add a value that is already there, nothing happens.
cities = {"Pune", "Kochi", "Pune", "Jaipur", "Kochi"}
print(len(cities))
print(sorted(cities))
orders = ["Rohtak", "Lucknow", "Rohtak", "Pune", "Lucknow", "Rohtak"]
unique_cities = set(orders)
print(len(unique_cities), "different cities")
print("Pune" in unique_cities)3 ['Jaipur', 'Kochi', 'Pune'] 3 different cities True
Two important facts:
- Sets have no order. When you print a set, the items can appear in any order, and that order can even change between runs. That is why these examples print
sorted(...). For the same reason, sets have no index:cities[0]givesTypeError: 'set' object is not subscriptable. {}is not an empty set. Empty curly braces make an empty dictionary. Writeset()for an empty set.
Set items must be hashable (unchangeable values such as numbers, strings and tuples). You cannot put a list inside a set.
Removing duplicates
set(items) is the quickest way to remove duplicates. But it throws away the original order. If order matters, use dict.fromkeys(), which keeps the first appearance of each value, because dictionaries remember insertion order:
attendance = ["Isha", "Rohan", "Isha", "Aarav", "Rohan", "Meera"]
print(len(set(attendance)), "different students")
print(list(dict.fromkeys(attendance)))4 different students ['Isha', 'Rohan', 'Aarav', 'Meera']
Fast membership tests
Checking x in some_list looks at the items one by one, so it gets slower as the list grows. Checking x in some_set uses the hash and takes about the same time whether the set has ten items or ten million. If you check membership many times, for example against a list of blocked usernames or valid PIN codes, convert the list to a set once and test against the set.
Adding and removing items
Sets are mutable, so you can add and remove items:
skills = {"Python", "Excel"}
skills.add("SQL")
skills.add("Python") # already there, nothing changes
skills.update(["Git", "HTML"])
print(sorted(skills))
skills.discard("Excel")
skills.discard("Java") # not there, no error
print(sorted(skills))['Excel', 'Git', 'HTML', 'Python', 'SQL'] ['Git', 'HTML', 'Python', 'SQL']
add(x)adds one item;update(iterable)adds many.discard(x)removes an item if it is there and does nothing otherwise.remove(x)also removes an item, but raisesKeyErrorif it is missing. Use it when a missing item would be a bug you want to hear about.
Set operations
This is where sets shine. Python gives you the operations from school maths with simple operators:
| Operator | Method | Result |
|---|---|---|
a | b | a.union(b) | Items in either set |
a & b | a.intersection(b) | Items in both sets |
a - b | a.difference(b) | Items in a but not in b |
a ^ b | a.symmetric_difference(b) | Items in exactly one of the sets |
a <= b | a.issubset(b) | True if every item of a is in b |
cricket = {"Aarav", "Kabir", "Rohan", "Farhan"}
coding = {"Kabir", "Isha", "Meera", "Rohan"}
print("Both clubs:", sorted(cricket & coding))
print("Either club:", sorted(cricket | coding))
print("Cricket only:", sorted(cricket - coding))
print("Exactly one club:", sorted(cricket ^ coding))
print({"Kabir", "Rohan"} <= cricket)Both clubs: ['Kabir', 'Rohan'] Either club: ['Aarav', 'Farhan', 'Isha', 'Kabir', 'Meera', 'Rohan'] Cricket only: ['Aarav', 'Farhan'] Exactly one club: ['Aarav', 'Farhan', 'Isha', 'Meera'] True
Without sets, each of these lines would need a loop and a few if statements. The method versions, such as cricket.union(coding), do the same job and also accept a list or any other iterable, while the operators need sets on both sides.
A practical example
A job posting asks for some skills, and a candidate has others. Sets answer "what is missing?" and "how good is the match?" in two lines:
required = {"Python", "SQL", "Git", "Pandas"}
priya = {"Python", "Excel", "SQL", "Communication"}
missing = required - priya
match = len(required & priya) / len(required)
print("Missing:", sorted(missing))
print(f"Match: {match:.0%}")Missing: ['Git', 'Pandas'] Match: 50%
frozenset: a set that cannot change
A frozenset is an immutable set: no add(), no discard(). Because it cannot change, it is hashable, so it can be a dictionary key or an item inside another set, which a normal set cannot. Create one with frozenset(["Python", "SQL"]). You will not need it often, but now you will recognise it.
Common mistakes
- Writing
{}for an empty set. It creates a dictionary. Useset(). - Expecting a set to keep order. Print
sorted(my_set)when order matters, or usedict.fromkeys()to remove duplicates in order. - Indexing a set.
my_set[0]fails. Loop over it, or convert it to a sorted list first. - Using
remove()when the item may be missing. It raisesKeyError. Usediscard().
Key points
- A set stores unique, hashable values in no particular order;
set()is an empty set. set(items)removes duplicates;dict.fromkeys(items)removes them and keeps order.x in a_setis fast, even for very large sets.add(),update(),discard()andremove()change a set.|,&,-and^give union, intersection, difference and symmetric difference.frozensetis an immutable, hashable set.
Exercise
Two shops in Lucknow sell these items: shop_a = ["rice", "dal", "tea", "sugar", "tea", "oil"] and shop_b = ["tea", "coffee", "oil", "biscuits", "dal"]. Convert both lists to sets and print, in sorted order: the items both shops sell, the items only shop A sells, and every item you can buy in either shop. Finally print how many different items there are in total.
Show solution
shop_a = ["rice", "dal", "tea", "sugar", "tea", "oil"]
shop_b = ["tea", "coffee", "oil", "biscuits", "dal"]
a = set(shop_a)
b = set(shop_b)
print("Both:", sorted(a & b))
print("Only A:", sorted(a - b))
all_items = a | b
print("Either:", sorted(all_items))
print(len(all_items), "different items")Both: ['dal', 'oil', 'tea'] Only A: ['rice', 'sugar'] Either: ['biscuits', 'coffee', 'dal', 'oil', 'rice', 'sugar', 'tea'] 7 different items
Converting to sets removes the duplicate "tea" in shop A. Intersection, difference and union then answer each question in one expression.
Quick Quiz
1. What does len({"a", "b", "a", "c", "b"}) return?
A set keeps only unique values, so "a", "b" and "c" remain.
2. Which line creates an empty set?
{} creates an empty dictionary; set() creates an empty set.
3. With a = {1, 2, 3} and b = {2, 3, 4}, what is a - b?
Difference keeps the items in a that are not in b.
4. What is the difference between discard(x) and remove(x)?
Use discard() when the item might not be there, and remove() when its absence would be a bug.
Learn Python with a mentor
Free lessons get you started. Our Python Programming training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
