Tuples
A tuple is a collection of values inside round brackets — parentheses — separated by commas. If that sounds like a list wearing different shoes, it very nearly is. The one real difference: a tuple is locked.
1Making a tuple
mixed = (10, -3.25, 5.891, 123, 'hello')
numbers = (10, 20, 30)
empty = ()
print(mixed)
print(numbers)
print(empty)(10, -3.25, 5.891, 123, 'hello') (10, 20, 30) ()
Same rules as a list: any number of values, mixed types allowed. Only the brackets changed — and with them, whether you are allowed to edit it later.
2The trap: a tuple of one item
This one catches everybody, and it is worth two minutes of your life. What do you think (5) is?
not_a_tuple = (5)
a_tuple = (5,)
print(type(not_a_tuple))
print(type(a_tuple))<class 'int'> <class 'tuple'>
(5) is not a tuple. It is just the number 5 with brackets around it, the same way (2 + 3) is just an expression in brackets. What makes a tuple is not the brackets — it is the comma.
(5,), with a trailing comma. It looks like a typo. It is not. Leave the comma out and you have an ordinary number.3It is a sequence, so it behaves
mixed = (100, 4.25, 'hi')
numbers = (10, 20, 30)
print(len(mixed))
print(numbers[0])
print(numbers[-1])
print((20, 40) + ('hi', 'bye'))
print((1, 2, 'hi') * 2)3 10 30 (20, 40, 'hi', 'bye') (1, 2, 'hi', 1, 2, 'hi')
Every common feature works, exactly as on a string and a list. Notice that + and * still work — they do not change the tuple, they build a brand new one, and a locked tuple has no objection to that.
4Locked: the one real difference
numbers = [10, 20, 30]
numbers[0] = 99 # a list allows it
print(numbers)
point = (10, 20, 30)
point[0] = 99 # a tuple refuses[99, 20, 30]
Traceback (most recent call last):
File "frozen.py", line 6, in <module>
point[0] = 99 # a tuple refuses
~~~~~^^^
TypeError: 'tuple' object does not support item assignmentThe list obeyed, and printed its new contents. The tuple refused out loud, and stopped the program. That is the whole difference between them, and every other fact about tuples follows from it.
[10, 20, 30](10, 20, 30)5A tuple has exactly two methods
A list had a dozen methods. A tuple has two — and that is not a gap in the language, it is the lock doing its job. Every list method that changed the list simply does not exist on a tuple: there is no append(), no remove(), no sort(). Ask for one and Python says it has never heard of it:
marks = (50, 20, 40)
marks.append(30) # tuples have no append()Traceback (most recent call last):
File "no_such_method.py", line 3, in <module>
marks.append(30) # tuples have no append()
^^^^^^^^^^^^
AttributeError: 'tuple' object has no attribute 'append'The two that survive are the two that only ask questions. Asking changes nothing, so a lock has no reason to stop you:
marks = (50, 20, 40, 20)
print(marks.count(20)) # how many 20s?
print(marks.index(20)) # where is the first 20?
print(marks.index(40))2 1 2
They behave exactly as they did on a list and on a string. count() answers how many, index() answers where — the first match only, which is why two 20s still give the single answer 1. Ask index() for something that is not there and it raises ValueError: tuple.index(x): x not in tuple.
6The functions work too
len(), min(), max() and sum() are functions — the tuple goes inside the parentheses. None of them changes anything, so all of them are allowed:
marks = (50, 20, 40, 20)
print(len(marks))
print(min(marks))
print(max(marks))
print(sum(marks))
print(sorted(marks))
print(marks)4 20 50 130 [20, 20, 40, 50] (50, 20, 40, 20)
sorted() gave back. Square brackets — it is a list, not a tuple. sorted() always builds a list, whatever you hand it. And the last line proves the tuple itself never moved, which is exactly what you would expect: it could not have, even if sorted() had wanted to.7tuple(): locking something you already have
tuple() is the last function, and it is the twin of list(): hand it any sequence and it gives you the tuple version.
letters = tuple('hello')
numbers = tuple([1, 2, 3])
empty = tuple()
print(letters)
print(numbers)
print(empty)('h', 'e', 'l', 'l', 'o')
(1, 2, 3)
()Together with list(), this is the honest answer to the question every student asks next: what if I really do need to change a tuple? You do not change it. You copy it into a list, change the list, and lock it again — and the result is a new tuple, which is why the rule was never broken:
marks = (50, 20, 40)
temp = list(marks) # 1. copy it into a list
temp.append(30) # 2. change the list
marks = tuple(temp) # 3. lock it again
print(marks)(50, 20, 40, 30)
8Why would anyone want a locked list?
It sounds like a weakness. It is a feature. Some data should not be editable — and when you put it in a tuple, Python guards it for you and refuses any accidental change, loudly, at once.
A date of birth. The days of the week. Latitude and longitude. Marks that have already been submitted. Lock them, and a bug cannot quietly rewrite them.
The students in a class. Items in a shopping cart. Anything that gets added to, removed from, or reordered.
9Try it at the prompt
10Recap
len(), indexing, slicing, + and * all work. It cannot be changed after it is made — that is the whole point of it, and the reason it has only two methods, count() and index(), both of which merely ask. len(), min(), max(), sum() and sorted() all work on it, and tuple() builds one from any sequence. And a tuple of one item needs a trailing comma: (5,).What is type((5))?
Which of these will Python refuse?
What does sorted((50, 20, 40)) give back?
Why does a tuple have no append() method?
You need to store a date of birth so nothing can overwrite it. What do you use?