Tuple¶
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
tuples.ipynb
tuples-sol.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. Exercises are graded by difficulty, from one star ✪ to four ✪✪✪✪
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 |
Result |
Meaning |
---|---|---|
|
|
Return the length of a tuple |
tuple |
|
Reads an element at specified index |
tuple |
|
Extracts a sub-tuple - return a NEW tuple |
tuple |
|
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 |
|
|
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
()[0]
(())[0]
type((())[0])
('a,')[0]
('a',)[0]
(1,2,3)[-0]
(1,2,3)[-1]
(1,2,3)[-3]
[ ]:
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]:
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)
[54]:
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)
()+()
type(()+())
len(()+())
()+[]
[]+()
(2,3,4) + tuple([5,6,7])
"crazy"+('r','o','c','k','e','t')
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:
[55]:
'e' in ('h','e','l','m','e','t')
[55]:
True
[56]:
'z' in ('h','e','l','m','e','t')
[56]:
False
not in¶
To check whether something is not belonging to a tuple, we can use two forms:
not in - form 1:
[57]:
"carrot" not in ("watermelon","banana","apple")
[57]:
True
[58]:
"watermelon" not in ("watermelon","banana","apple")
[58]:
False
not in - form 2
[59]:
not "carrot" in ("watermelon","banana","apple")
[59]:
True
[60]:
not "watermelon" in ("watermelon","banana","apple")
[60]:
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')
[ ]:
Multiplication¶
To replicate the elements in a tuple, it is possible to use the operator *
which produces a NEW tuple:
[61]:
(7,8,5) * 3
[61]:
(7, 8, 5, 7, 8, 5, 7, 8, 5)
[62]:
(7,8,5) * 1
[62]:
(7, 8, 5)
[63]:
(7,8,5) * 0
[63]:
()
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')
[64]:
x = (2,4,3)
y = (('w','e','l','c'),('o',),('m','e'))
# write here
('w', 'e', 'l', 'c', 'w', 'e', 'l', 'c', 'o', 'o', 'o', 'o', 'm', 'e', 'm', 'e', 'm', 'e')
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:
[65]:
# 0 1 2 3 4 5 6
tup = (17,54,34,87,26,95,34)
[66]:
tup = tup[0:3] + (12,) + tup[4:]
[67]:
tup
[67]:
(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:
[68]:
# 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')
[69]:
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')
[70]:
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)
[71]:
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 |
Return |
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.
[72]:
tup = ('b','a','r','a','t','t','o')
[73]:
tup.index('b')
[73]:
0
[74]:
tup.index('a')
[74]:
1
[75]:
tup.index('t')
[75]:
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
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(())
count
method¶
We can obtain the number of occurrences of a certain element in a list by using the method count
:
[76]:
t = ('a', 'c', 'a', 'd', 'e', 'm', 'i', 'a')
[77]:
t.count('a')
[77]:
3
[78]:
t.count('d')
[78]:
1
If an element is not present 0
is returned:
[79]:
t.count('z')
[79]:
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
[80]:
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
Exercises with functions¶
WARNING: following exercises require to know:
If you are just a beginner, you may skip them and come back later.Exercise - touples¶
✪✪ Let’s call a touple a tuple with a couple of elements. Write a function touples
which given a tuple, RETURNs a list having as elements touples each taken in alternation from t
.
if the input tuple
t
has an odd number of elements, the last tuple in the list to return will be made of only one element
Example:
>>> touples( ('c', 'a', 'r', 'p', 'e', 't') ) # even length
[('c', 'a'), ('r', 'p'), ('e', 't')]
>>> touples( ('s','p','i','d','e','r','s') ) # odd length
[('s', 'p'), ('i', 'd'), ('e', 'r'), ('s',)]
[81]:
# write here
Exercise - joined¶
✪✪ Write a function which given two tuples of characters ta
and tb
having each different characters (may also be empty), return a tuple made like this:
if the tuple
ta
terminates with the same charactertb
begins with, RETURN the concatenation ofta
andyb
WITHOUT duplicated charactersotherwise RETURN an empty tuple
Example:
>>> joined(('a','b','c'), ('c','d','e'))
('a', 'b', 'c', 'd', 'e')
>>> joined(('a','b'), ('b','c','d'))
('a', 'b', 'c', 'd')
>>> joined((),('e','f','g'))
()
>>> joined(('a',),('e','f','g'))
()
>>> f(('a','b','c'),())
()
>>> f(('a','b','c'),('d','e'))
()
[82]:
# write here
Verify comprehension¶
WARNING
The following exercises contain tests with assert. To understand how to do them, read first Error handling and testing
doubles¶
✪✪ Take as input a list of n
integer numbers, and RETURN a NEW list which contains n
tuples each having two elements. Each tuple contains a number taken from the corresponding position in the original list, and its double.
Example - given:
doubles([ 5, 3, 8])
it must produce the list:
[(5,10), (3,6), (8,16)]
[83]:
def doubles(lst):
raise Exception('TODO IMPLEMENT ME !')
# TEST START - DO NOT TOUCH !
assert doubles([]) == []
assert doubles([3]) == [(3,6)]
assert doubles([2,7]) == [(2,4),(7,14)]
assert doubles([5,3,8]) == [(5,10), (3,6), (8,16)]
# verify the original list was not changed
la = [6]
lb = doubles(la)
assert la == [6]
assert lb == [(6,12)]
# TEST END
nasty¶
✪✪✪ Given two tuples ta
and b
, ta
made of characters and tb
of positive integer numbers , write a function nasty
which RETURNS a tuple having two character strings: the first character is taken from ta
, the second is a number taken from the corresponding position in tb
. The strings are repeated for a number of times equal to that number.
>>> nasty(('u','r','g'), (4,2,3))
('u4', 'u4', 'u4', 'u4', 'r2', 'r2', 'g3', 'g3', 'g3')
>>> nasty(('g','a','s','p'), (2,4,1,3))
('g2', 'g2', 'a4', 'a4', 'a4', 'a4', 's1', 'p3', 'p3', 'p3')
[84]:
# write here