Sets
Let's go back to the stall. Next to the price board hangs a second one, "in stock": it holds only names, with no prices. Each name is written once, because there is no point in writing pear twice.
That is how a set works: it stores each value once. For example, in a list of tags the same word may repeat, but you need only the distinct tags. The set function builds a set from a list and drops the repeats:
tags = ["python", "web", "python", "api", "web"]
unique_tags = set(tags)
print(len(tags), len(unique_tags)) # 5 3
print(sorted(unique_tags)) # ['api', 'python', 'web']
print("api" in unique_tags) # TrueLet's go through it line by line:
set(tags)drops the repeats: of the five tags, three distinct ones remain.print(len(tags), len(unique_tags))prints5 3.sorted(unique_tags)returns a list in alphabetical order, which is how a set is printed in a predictable order."api" in unique_tagschecks whether the element is there and givesTrue.
No order and no indices
A set literal lists the elements in curly braces: {1, 2, 3}. The elements have no order: print may show them in any order, so for output a set is wrapped in sorted. There are no indices or slices either: unique_tags[0] raises TypeError: 'set' object is not subscriptable.
This is where the "in stock" board stops being an exact picture. Its rows go from top to bottom, but a set has neither a first element nor a last one.
So set(tags) drops the repeats but does not keep the order of the list. A set fits when the order does not matter: for example, to find out how many different tags a list holds.
The add and remove methods
The add method adds an element, and a repeat changes nothing. The remove method deletes an element:
team = {"ann", "bob"}
team.add("eve")
team.add("ann")
team.remove("bob")
print(sorted(team)) # ['ann', 'eve']Let's go through it line by line:
team.add("eve")adds a new player.team.add("ann")changes nothing:"ann"is already in the set.team.remove("bob")deletes"bob", and['ann', 'eve']remain.
If the element is missing, remove stops the program with a KeyError, like reading a missing dict key.
Hashable elements
A set is built like the keys of a dict without the values. Two things follow from this:
- the elements must be hashable, so a list cannot go into a set:
{[1, 2]}raisesTypeError: unhashable type: 'list'; - like a dict, a set finds an element by its hash, without a scan, so
inis much faster here than in a long list.
The immutable variant of a set is the frozenset type. It is hashable, so it works as a dict key or an element of another set.
Interviewers like to ask this: "How does set differ from frozenset?" The answer: a set can be changed with add and remove. A frozenset does not change after it is created. In return, a frozenset is hashable, and a set is not.
Operations
Two sets can be compared with three operators. Each operation returns a new set, and the original ones do not change:
team_a = {"ann", "bob", "eve"}
team_b = {"bob", "kim"}
print(sorted(team_a | team_b)) # ['ann', 'bob', 'eve', 'kim']
print(sorted(team_a & team_b)) # ['bob']
print(sorted(team_a - team_b)) # ['ann', 'eve']
print(sorted(team_b - team_a)) # ['kim']Union |
The | operator gives the union: all the elements of both sets, each one once. "bob" plays in both teams, but in team_a | team_b he appears once.
Intersection &
The & operator gives the intersection: the common elements. Here team_a & team_b is the players of both teams, that is, only "bob".
Difference -
The - operator gives the difference: the elements of the first set that are not in the second. team_a - team_b is those who play only in the first team.
The difference depends on the order of the operands: team_b - team_a gives ['kim']. The union and the intersection do not depend on the order.
Common mistake
An empty set is written as {}:
seen = {}
seen.add("ann") # ✗AttributeError: 'dict' object has no attribute 'add'Empty curly braces create a dict, and a dict has no add method. An empty set is created only by calling set().
Key points
- A set stores each value once, and
set(a_list)drops the repeats. - A set has no order and no indices, so for output it is wrapped in
sorted. - The elements of a set must be hashable, and
frozensetis an immutable, hashable set. |,&and-give the union, the intersection and the difference; onlyset()creates an empty set.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.