Python course Β· Module 2: Data Structures
Tuples and Sets - Permanent Records and Unique Species
In this lesson4
Welcome! On an expedition you come across data for which a list is not the best choice. The first example is the coordinates of a waterhole: a pair of numbers that should never change. If some function overwrote one of them by mistake, the whole team would look for water in the wrong place. The second example is a register of species seen today. A zebra walked past the camp five times, but it is still one species, while a list would record it five times.
Python has two tools for these situations. A tuple is a record that cannot be changed. A set is a collection in which every element appears only once.
A Tuple - an Entry in Ink
A list is like notes in pencil that you can erase and add to. A tuple is an entry in ink in your journal: once written, it stays forever. You create it with round brackets and separate the elements with commas:
1waterhole = (-2.33, 34.83)
2lion_record = ("Lion", 190, True)
3print(waterhole[0]) # -2.33
4print(lion_record[1]) # 190Indexing works exactly like in a list, starting from zero. A tuple can also mix data types: lion_record stores a name, a weight and whether the animal is dangerous.
The Comma Makes the Tuple
There is one detail that trips up many beginners: it is the comma, not the brackets, that creates a tuple. You can see it best with a one-element tuple, checked with the type() function from the first module:
1single = ("Lion",)
2not_a_tuple = ("Lion")
3print(type(single)) # <class 'tuple'>
4print(type(not_a_tuple)) # <class 'str'>Without the comma, Python sees ordinary text in brackets, the same kind as in math expressions. For the same reason, writing point = 10.5, 20.3 also creates a tuple. The brackets are optional then, but I recommend always writing them, because it is immediately clear that this is a tuple.
Immutability
Let's try to correct a coordinate of the waterhole the way we would in a list:
1waterhole = (-2.33, 34.83)
2waterhole[0] = -2.40 # TypeError!Python raises a TypeError, because a tuple cannot be changed after it is created. That is not a flaw but a guarantee: the coordinates will not change because of a typo in another part of the program. That is why a tuple has no append(), remove() or sort() methods. It has only two methods left, and both just read the data: count() and index().
Unpacking a Tuple
You can split a record tuple into separate variables in one move. On the left side of the = sign you give as many names as the tuple has elements:
1name, weight, dangerous = lion_record
2print(name) # Lion
3print(weight) # 190Each variable got the element from the same position, and the tuple itself stayed unchanged. If the number of names does not match the number of elements, Python raises a ValueError. You already know unpacking from the for key, value in catalog.items() loop, because the items() method gives you exactly such tuples with a key and a value.
So when a tuple and when a list? My rule: if the data describes one thing with a fixed shape, like coordinates or an animal record, choose a tuple. If it is a collection that grows and shrinks, like today's sightings, choose a list.
A Set - a Register of Unique Species
Let's go back to the zebra that visited the camp five times. A set works like an attendance list at the waterhole: you tick off each species once, even if it came to drink ten times. The simplest way to build one is to pass a list through the set() function:
1sightings = ["Zebra", "Lion", "Zebra", "Elephant", "Zebra"]
2species = set(sightings)
3print(species) # {'Lion', 'Zebra', 'Elephant'}
4print(len(species)) # 3The duplicates are gone, and the sightings list still has five entries, because the set() function built a new collection. The order in the printout may be different for you, because a set does not remember the order of its elements. For that reason it has no indexes, and species[0] ends with an error.
Creating and Changing a Set
You can also write a set directly, in curly braces. Watch out for one trap: empty braces {} create an empty dictionary, not a set, so you write an empty set as set().
1visitors = {"Zebra", "Lion"}
2visitors.add("Elephant")
3visitors.add("Zebra")
4print(len(visitors)) # 3
5print("Lion" in visitors) # TrueUnlike a tuple, a set is mutable. The add() method added the elephant, but the second zebra changed nothing, because it was already in the register. The in operator checks membership very quickly, even in a huge set. Two methods remove elements: remove(), which raises an error when the element is missing, and discard(), which then simply does nothing. With uncertain data I recommend discard().
Set Operations
The real power of sets shows only when you compare two registers. In the morning and in the evening the team records the species at the waterhole, and three operators answer three different questions:
1morning = {"Zebra", "Lion", "Elephant"}
2evening = {"Zebra", "Hippo", "Elephant"}
3print(morning & evening) # {'Zebra', 'Elephant'}
4print(morning | evening) # {'Zebra', 'Lion', 'Elephant', 'Hippo'}
5print(morning - evening) # {'Lion'}The & operator is the intersection, meaning the species seen both in the morning and in the evening. The | operator is the union: everything that appeared during the day, without repeats. The - operator is the difference, meaning the morning species that were missing in the evening. None of them changes the morning or evening sets, each one builds a new set with the result. For the difference the order matters: evening - morning gives {'Hippo'}. Everything works the same way with numbers, so {1, 2, 3} & {2, 3, 4} returns {2, 3}.
Which Structure to Choose?
You now know four data structures, and each has its place in an explorer's kit:
- list - ordered and changeable, allows duplicates, like a sighting journal,
- tuple - ordered and unchangeable, like coordinates or a fixed record,
- set - no order and no duplicates, like a register of unique species,
- dictionary - key and value pairs, like a catalog of discoveries with cards.
When you need unique elements, choose a set instead of guarding a list against duplicates by hand.
Remember: a tuple is an entry in ink that you cannot change, and a set is a register in which every species appears only once. In the next lesson Darwin will show you list comprehensions, and in the project at the end of the module tuples and sets will help you analyze the expedition journal.
Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. How does a tuple differ from a list?
2. What is the main feature of a set?
3. What does {1, 2, 3} & {2, 3, 4} return?
Hands-on tasks in the game
- Code editor
Create a tuple called 'coordinates' with values: 10.5, 20.3, 15.7
- Code editor
Remove the duplicates from the list numbers = [1, 2, 2, 3, 3, 3, 4] with set(), store the result in the variable unique and print it
- Horizontal ordering
Arrange the elements in the correct order:
- Click in order
Click the elements in the correct order:
- Vertical ordering
Arrange the steps in order: