Tuples
Download exercise zip
A tuple in Python is an immutable sequence of heterogenous elements which allows duplicates, so we can put inside the objects we want, of different types, and with repetitions.
What to do
Unzip exercises zip in a folder, you should obtain something like this:
tuples
tuples1.ipynb
tuples1-sol.ipynb
tuples2-chal.ipynb
jupman.py
WARNING: to correctly visualize the notebook, it MUST be in an unzipped folder !
open Jupyter Notebook from that folder. Two things should open, first a console and then a browser. The browser should show a file list: navigate the list and open the notebook
tuples.ipynb
Go on reading the exercises file, sometimes you will find paragraphs marked Exercises which will ask to write Python commands in the following cells.
Shortcut keys:
to execute Python code inside a Jupyter cell, press
Control + Enter
to execute Python code inside a Jupyter cell AND select next cell, press
Shift + Enter
to execute Python code inside a Jupyter cell AND a create a new cell aftwerwards, press
Alt + Enter
If the notebooks look stuck, try to select
Kernel -> Restart
Creating tuples
Tuples are created with round parenthesis ()
and by separating the elements with commas ,
Some example:
[2]:
numbers = (6,7,5,7,7,9)
[3]:
print(numbers)
(6, 7, 5, 7, 7, 9)
Tuples of one element: You can create a tuple of a single element by adding a comma after the element:
[4]:
little_tup = (4,) # notice the comma !!!
Let’s verify the type is the expected one:
[5]:
type(little_tup)
[5]:
tuple
To see the difference, we write down here (4)
without comma and we verify the type of the obtained object:
[6]:
fake = (4)
[7]:
type(fake)
[7]:
int
We see that fake
is an int
, because 4
has been evaluated as an expression inside round brackets so the result is the content inside the parenthesis.
Empty tuple
We can also create an empty tuple:
[8]:
empty = ()
[9]:
print(empty)
()
[10]:
type(empty)
[10]:
tuple
Tuples without brackets
When we assign values to some variable, (and only when we assign values to variables) it is possible to use a notation like the following, in which on the left of =
we put names of variables and on the right we place a sequence of values:
[11]:
a,b,c = 1, 2, 3
[12]:
a
[12]:
1
[13]:
b
[13]:
2
[14]:
c
[14]:
3
If we ask ourselves what that 1,2,3
is, we can try putting on the left a single variable:
[15]:
# WARNING: BETTER AVOID THIS!
x = 1,2,3
[16]:
type(x)
[16]:
tuple
We see that Python considered that 1,2,3
as a tuple. Typically, you would never write assignments with less variables than values to put, but if it happens, probably you will find yourself with some undesired tuple !
QUESTION: Have a look at the following code snippets, and for each try guessing which result it produces (or if it gives an error)
z,w = 5,6 print(type(z)) print(type(w))
a,b = 5,6 a,b = b,a print('a=',a) print('b=',b)
z = 5, print(type(z))
z = , print(type(z))
Heterogenous elements
In a tuple we can put elements of different types, like numbers and strings:
[17]:
stuff = (4, "paper", 5, 2,"scissors", 7)
[18]:
stuff
[18]:
(4, 'paper', 5, 2, 'scissors', 7)
[19]:
type(stuff)
[19]:
tuple
We can also insert other tuples:
[20]:
salad = ( ("lettuce", 3), ("tomatoes",9), ("carrots",4) )
[21]:
salad
[21]:
(('lettuce', 3), ('tomatoes', 9), ('carrots', 4))
[22]:
type(salad)
[22]:
tuple
And also lists:
[23]:
mix = ( ["when", "it", "rains"], ["I", "program"], [7,3,9] )
WARNING: avoid mutable objects inside tuples!
Inserting mutable objects like lists inside tuples may cause problems in some situations like when you later want to use the tuple as element of a set or a key in a dictionary (we will see the details in the respective tutorials)
Let’s see how the previous examples are represented in Python Tutor:
[24]:
# WARNING: before using the function jupman.pytut() which follows,
# it is necessary to first execute this cell with Shift+Enter (once is enough)
import jupman
[25]:
stuff = (4, "paper", 5, 2,"scissors", 7)
salad = ( ("lettuce", 3), ("tomatoes",9), ("carrots",4) )
mix = ( ["when", "it", "rains"], ["I", "program"], [7,3,9] )
jupman.pytut()
[25]:
Creating tuples from sequences
You can create a tuple from any sequence, like for example a list:
[26]:
tuple( [8,2,5] )
[26]:
(8, 2, 5)
Or a string (which is a character sequence):
[27]:
tuple("abc")
[27]:
('a', 'b', 'c')
Creating sequences from tuples
Since the tuple is a sequence, it is also possible to generate lists from tuples:
[28]:
list( (3,4,2,3) )
[28]:
[3, 4, 2, 3]
QUESTION: Does is it make sense creating a tuple from another tuple like this? Can we rewrite the code in a more concise way?
[29]:
x = (4,2,5)
y = tuple(x)
QUESTION: Have a look at the following expressions, and for each try to guess which result produces (or if it gives an error):
(1.2,3.4)
(1;2;3;4)
(1,2;3,4)
(1,2,3,4)
(())
type(())
((),)
tuple([('a'),('b'),('c')])
tuple(tuple(('z','u','m')))
str(('a','b','c'))
"".join(('a','b','c'))
Operators
The following operators work on tuples and behave exactly as in lists:
Operator |
Syntax |
Result |
Meaning |
---|---|---|---|
|
|
Return the length of a tuple |
|
tuple |
|
Reads an element at specified index |
|
tuple |
|
Extracts a sub-tuple - return a NEW tuple |
|
tuple1 |
|
Concatenates two tuples - return a NEW tuple |
|
obj |
|
Checks whether an element is present in a tuple |
|
tuple |
|
Replicates the tuple - return a NEW tuple |
|
equality |
|
|
Checks if two tuples are equal or different |
len
len
function returns the tuple length:
[30]:
len( (4,2,3) )
[30]:
3
[31]:
len( (7,) )
[31]:
1
[32]:
len( () )
[32]:
0
QUESTION: Have a look at following expressions, and for each try to guess the result (or if it gives an error)
len(3,2,4)
len((3,2,4))
len(('a',))
len(('a,'))
len(((),(),()))
len(len((1,2,3,4)))
len([('d','a','c','d'),(('ab')),[('a','b','c')]])
[ ]:
Reading an element
Like in strings and lists by using brackets we can read an element at a certain position:
[33]:
# 0 1 2 3
tup = (10,11,12,13)
[34]:
tup[0]
[34]:
10
[35]:
tup[1]
[35]:
11
[36]:
tup[2]
[36]:
12
[37]:
tup[3]
[37]:
13
We can also use negative indexes:
[38]:
tup[-1]
[38]:
13
QUESTION: Have a look at the following expressions and for each of them try to guess the result or if it produces an error:
(1,2,3)[0]
(1,2,3)[3]
(1,2,3)0
('a,')[0]
('a',)[0]
(1,2,3)[-0]
(1,2,3)[-1]
(1,2,3)[-3]
()[0]
(())[0]
type((())[0])
[ ]:
Exercise - animals
Given the string animals = "Siamese cat,dog,canary,piglet,rabbit,hamster"
convert it to a list
create a tuple of tuples where each tuple has two elements: the animal name and the name length, i.e. ((“dog”,3), ( “hamster”,7))
print the tuple
You should obtain:
Siamese cat,dog,canary,piglet,rabbit,hamster
(('Siamese cat', 11), ('dog', 3), ('canary', 6), ('piglet', 6), ('rabbit', 6), ('hamster', 7))
you can assume
animals
always contains exactly 6 animals
[39]:
animals = "Siamese cat,dog,canary,piglet,rabbit,hamster"
# write here
Slices
As with strings and lists, by using slices we can also extract subsequences from a tuple, that is, on the right of the tuple we can write square brackets with inside a start index INCLUDED, a colon :
and an end index EXCLUDED:
[40]:
tup = (10,11,12,13,14,15,16,17,18,19)
[41]:
tup[2:6] # from index 2 INCLUDED to 6 EXCLUDED
[41]:
(12, 13, 14, 15)
It is possible to alternate the gathering of elements by adding the number of elements to skip as a third numerical parameter in the square brackets, for example:
[42]:
tup = (10,11,12,13,14,15,16,17)
[43]:
tup[0:8:5]
[43]:
(10, 15)
[44]:
tup[0:8:2]
[44]:
(10, 12, 14, 16)
[45]:
tup[1:8:1]
[45]:
(11, 12, 13, 14, 15, 16, 17)
WARNING: remeber that slices produce a NEW tuple !
QUESTION: Have a look at the following code snippets, and for each try to guess which result it produces (or if it gives an error)
(7,6,8,9,5)(1:3)
(7,6,8,9,5)[1:3]
(10,11,12,13,14,15,16)[3:100]
(10,11,12,13,14,15,16)[-3:5]
(1,0,1,0,1,0)[::2]
(1,2,3)[::1]
(1,0,1,0,1,0)[1::2]
tuple("postcards")[0::2]
(4,5,6,3,4,7)[0:::2]
Concatenation
It is possible to concatenate two tuples by using the operator +
, which creates a NEW tuple:
[46]:
t = (1,2,3) + (4,5,6,7,8)
[47]:
t
[47]:
(1, 2, 3, 4, 5, 6, 7, 8)
[48]:
type(t)
[48]:
tuple
Let’s verify that original tuples are not modified:
[49]:
x = (1,2,3)
y = (4,5,6,7,8)
[50]:
t = x + y
[51]:
t
[51]:
(1, 2, 3, 4, 5, 6, 7, 8)
[52]:
x
[52]:
(1, 2, 3)
[53]:
y
[53]:
(4, 5, 6, 7, 8)
Let’s see how they are represented in Python Tutor:
[54]:
# FOR PYTHON TUTOR TO WORK, REMEMBER TO EXECUTE HERE THIS CELL with Shift+Enter
# (it's sufficient to execute it only once, it's also at the beginning of this notebook)
import jupman
[55]:
x = (1,2,3)
y = (4,5,6,7,8)
t = x + y
print(t)
print(x)
print(y)
jupman.pytut()
(1, 2, 3, 4, 5, 6, 7, 8)
(1, 2, 3)
(4, 5, 6, 7, 8)
[55]:
QUESTION: Have a look at the following code snippets, and for each try guessing which result it produces (or if it gives an error)
(2,3,4) + tuple([5,6,7])
"crazy"+('r','o','c','k','e','t')
()+()
type(()+())
len(()+())
()+[]
[]+()
Membership
As in all sequences, if we want to verify whether an element is contained in a tuple we can use the operator in
which returns a boolean value:
[56]:
'e' in ('h','e','l','m','e','t')
[56]:
True
[57]:
'z' in ('h','e','l','m','e','t')
[57]:
False
not in
To check whether something is not belonging to a tuple, we can use two forms:
not in - form 1:
[58]:
"carrot" not in ("watermelon","banana","apple")
[58]:
True
[59]:
"watermelon" not in ("watermelon","banana","apple")
[59]:
False
not in - form 2
[60]:
not "carrot" in ("watermelon","banana","apple")
[60]:
True
[61]:
not "watermelon" in ("watermelon","banana","apple")
[61]:
False
QUESTION: Have a look at the following code snippets, and for each try to guess which result it produces (or if it gives an error)
3 in (1.0, 2.0,3.0)
3.0 in (1,2,3)
3 not in (3)
3 not in (3,)
6 not in ()
0 in (0)[0]
[] in ()
() in []
not [] in ()
() in ()
() in (())
() in ((),)
'ciao' in ('c','i','a','o')
Replication
To replicate the elements in a tuple, it is possible to use the operator *
which produces a NEW tuple:
[62]:
(7,8,5) * 3
[62]:
(7, 8, 5, 7, 8, 5, 7, 8, 5)
[63]:
(7,8,5) * 1
[63]:
(7, 8, 5)
[64]:
(7,8,5) * 0
[64]:
()
QUESTION: What is the following code going to print?
x = (5,6,7)
y = x * 3
print('x=',x)
print('y=',y)
ANWSER: It will print:
x = (5, 6, 7)
y = (5, 6, 7, 5, 6, 7, 5, 6, 7)
because the multiplication generates a NEW tuple which is associated to y
. The tuple associated to x
remains unchanged.
QUESTION: Have a look at the following expressions, and for each try to guess which result it produces (or if it gives an error)
(5,6,7)*(3.0)
(5,6,7)*(3,0)
(5,6,7)*(3)
(5,6,7)*3
(4,2,3)*int(3.0)
(1,2)*[3][0]
(1,2)*(3,4)[-1]
[(9,8)]*4
(1+2,3+4)*5
(1+2,)*4
(1+2)*4
(1,2,3)*0
(7)*0
(7,)*0
[ ]:
Exercise - welcome
Given a tuple x
containing exactly 3 integers, and a tuple y
containing exactly 3 tuples of characters, write some code to create a tuple z
containing each tuple of y
replicated by the corresponding integer in x
.
Example - given:
x = (2,4,3)
y = (('w','e','l','c'),('o',),('m','e'))
after your code it should print:
>>> print(z)
('w', 'e', 'l', 'c', 'w', 'e', 'l', 'c', 'o', 'o', 'o', 'o', 'm', 'e', 'm', 'e', 'm', 'e')
[65]:
x = (2,4,3)
y = (('w','e','l','c'),('o',),('m','e'))
# write here
Write an element
Tuples are immutable, so trying to i.e. write an assignment for placing the number 12
into the cell at index 3
provokes an error:
# 0 1 2 3 4
tup = (5,8,7,9,11)
tup[3] = 666
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-118-83949b0c81e2> in <module>
1 tup = (5,8,7,9,11)
----> 2 tup[3] = 666
TypeError: 'tuple' object does not support item assignment
What we can do is to create a NEW tuple by composing it from sequences takes from the original one:
[66]:
# 0 1 2 3 4 5 6
tup = (17,54,34,87,26,95,34)
[67]:
tup = tup[0:3] + (12,) + tup[4:]
[68]:
tup
[68]:
(17, 54, 34, 12, 26, 95, 34)
WARNING: append
, extend
, insert
, sort
DO NOT WORK WITH TUPLES !
All the methods you used to modify lists will not work with tuples.
Exercise - badmod
Try writing down here (1,2,3).append(4)
and see which error appears:
[69]:
# write here
Exercise - abde
Given a tuple x
, save in a variable y
another tuple containing:
at the beginning, the same elements of
x
except the last oneat the end, the elements
'd'
and'e'
.Your code should work with any tuple
x
Example - given:
x = ('a','b','c')
after your code, you should see printed:
x = ('a', 'b', 'c')
y = ('a', 'b', 'd', 'e')
[70]:
x = ('a','b','c')
# write here
Exercise - charismatic
Given a tuple t
having alternating uppercase / lowercase characters, write some code which modifies the assignment of t
so that t
becomes equal to a tuple having all characters lowercase as first ones and all uppercase characters as last ones.
Example - given:
t = ('C', 'h','A', 'r', 'I', 's', 'M', 'a', 'T', 'i', 'C')
after your code it must result:
>>> print(t)
('C', 'A', 'I', 'M', 'T', 'C', 'h', 'r', 's', 'a', 'i')
[71]:
t = ('C', 'h','A', 'r', 'I', 's', 'M', 'a', 'T', 'i', 'C')
# write here
Exercise - sorting
Given a tuple x
of unordered numbers, write some code which changes the assignment of x
so that x
results assigned to a sorted tuple
your code must work for any tuple
x
HINT: as we’ve already written, tuples DO NOT have
sort
method (because it would mutate them), but lists have it …
Example - given:
x = (3,4,2,5,5,5,2,3)
after your code it must result:
>>> print(x)
(2, 2, 3, 3, 4, 5, 5, 5)
[72]:
x = (3,4,2,5,5,5,2,3)
# write here
Methods
Tuples are objects of type typle
and have methods which allows to operate on them:
Method |
Returns |
Description |
---|---|---|
|
Searches for the first occurence of an element and returns its position |
|
|
Count the occurrences of an element |
index
method
index
method allows to find the index of the FIRST occurrence of an element.
[73]:
tup = ('b','a','r','a','t','t','o')
[74]:
tup.index('b')
[74]:
0
[75]:
tup.index('a')
[75]:
1
[76]:
tup.index('t')
[76]:
4
If the element we’re looking for is not present, we will get an error:
>>> tup.index('z')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-318-96cf33478b69> in <module>
----> 1 tup.index('z')
ValueError: tuple.index(x): x not in tuple
Optionally, you can specify an index to start searching from (included):
[77]:
# 0 1 2 3 4 5 6 7 8
('b','a','r','a','t','t','a','r','e').index('r',3)
[77]:
7
and also where to end (excluded):
# 0 1 2 3 4 5 6 7 8
('b','a','r','a','t','t','a','r','e').index('r',3,7)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-12-e91a1f6569d7> in <module>
1 # 0 1 2 3 4 5 6 7 8
----> 2 ('b','a','r','a','t','t','a','r','e').index('r',3,7)
ValueError: tuple.index(x): x not in tuple
Do not abuse index
WARNING: index
is often used in a wrong / inefficient ways
Always ask yourself:
Could the tuple contain duplicates? Remember only the first will be found!
Could the tuple not contain the searched element? Remember to also handle this case!
index
performs a search on all the tuple, which could be inefficient: is it really needed, or do we already know the interval where to search?If we want to know if an
element
is in a position we already know (i.e.3
),index
is useless, it’s enough to writemy_tuple[3] == element
. If you usedindex
, it could discover duplicate characters which are before or after the one we are interested in!
QUESTION: Have a look at the following expressions, and for each try to guess which result (or if it gives an error)
(3,4,2).index(4)
(3,4,---1).index(-1)
(2.2,.2,2,).index(2)
(3,4,2).index(len([3,8,2,9]))
(6,6,6).index(666)
(4,2,3).index(3).index(3)
tuple("GUG").index("g")
(tuple("ci") + ("a","o")).index('a')
(()).index(())
((),).index(())
Exercise - The chinese boxes
Write some code which searches the word "Chinese"
in each of 3 tuples nested into each other, printing the actual position relative to the tuple which contains the occurrance.
the tuples always start with 4 strings
Example - given:
tup = ('Open','The','Chinese','Boxes', ('Boxes','Open','The','Chinese', ('Chinese', 'Open','The','Boxes')))
after your code, it must print:
('Open', 'The', 'Chinese', 'Boxes') contains Chinese at position 2
('Boxes', 'Open', 'The', 'Chinese') contains Chinese at position 3
('Chinese', 'Open', 'The', 'Boxes') contains Chinese at position 0
[78]:
word = 'Chinese'
tup = ('Open','The','Chinese','Boxes', ('Boxes','Open','The','Chinese', ('Chinese', 'Open','The','Boxes')))
# 2 3 0
#word = 'c'
#tup = ('a','b','c','d',('e','c','g','h',('a','b','d','c')))
# 2 1 3
# write here
count
method
We can obtain the number of occurrences of a certain element in a list by using the method count
:
[79]:
t = ('a', 'c', 'a', 'd', 'e', 'm', 'i', 'a')
[80]:
t.count('a')
[80]:
3
[81]:
t.count('d')
[81]:
1
If an element is not present 0
is returned:
[82]:
t.count('z')
[82]:
0
Do not abuse count
WARNING: count
is often used in a wrong / inefficient ways
Always ask yourself:
Could the tuple contain duplicates? Remember they will all be counted!
Could the tuple not contain the element to count? Remember to also handle this case!
count
performs a search on all the tuple, which could be inefficient: is it really needed, or do we already know the interval where to search?
QUESTION: Have a look at the following expressions, and for each try to guess which result (or if it gives an error)
('p', 'o', 'r', 't', 'e', 'n', 't', 'o', 's', 'o').count('o')
('p', 'o', 'r', 't', 'e', 'n', 't', 'o', 's', 'o').count( ('o') )
('p', 'o', 'r', 't', 'e', 'n', 't', 'o', 's', 'o').count( ('o',) )
(1,0,0,0).count( 0 )
(1,0,0,0).count( (0) )
(1,0,0,0).count( (0,) )
(1,0,(0,),(0,)).count( (0,) )
(1,0,(0.0),((0,0),(0,0))).count( (0,0) )
Exercise - fruits
Given the string s = "apple|pear|apple|cherry|pear|apple|pear|pear|cherry|pear|strawberry"
Insert the elements separated by "|"
(pipe character) in a list.
How many elements must the list have?
Knowing the list created at previous point has only four distinct elements (es
"apple"
,"pear"
,"cherry"
, and"strawberry"
), create another list where each element is a tuple containing the name of the fruit and its multiplicity (that is, the number of times it appears in the original list).
Example - given:
counts = [("apple", 3), ("pear",5), ...]
Here you can write code which works given a specific constant, so you don’t need cycles.
Print the content of each tuple in a separate line (i.e.: first libe;
"apple"
is present 3 times)
You should obtain:
[('apple', 3), ('pear', 5), ('cherry', 2), ('strawberry', 1)]
apple is present 3 times
pear is present 5 times
cherry is present 2 times
strawberry is present 1 times
[83]:
s = "apple|pear|apple|cherry|pear|apple|pear|pear|cherry|pear|strawberry"
# write here
[('apple', 3), ('pear', 5), ('cherry', 2), ('strawberry', 1)]
apple is present 3 times
pear is present 5 times
cherry is present 2 times
strawberry is present 1 times
Continue
Go on with the first challenges