Tuples

Download exercise zip

Browse files online

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

  1. 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 !

  1. 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

  2. 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)

  1. z,w = 5,6
    print(type(z))
    print(type(w))
    
  2. a,b = 5,6
    a,b = b,a
    print('a=',a)
    print('b=',b)
    
  3. z = 5,
    print(type(z))
    
  4. 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)
Show answer

QUESTION: Have a look at the following expressions, and for each try to guess which result produces (or if it gives an error):

  1. (1.2,3.4)
    
  2. (1;2;3;4)
    
  3. (1,2;3,4)
    
  4. (1,2,3,4)
    
  5. (())
    
  6. type(())
    
  7. ((),)
    
  8. tuple([('a'),('b'),('c')])
    
  9. tuple(tuple(('z','u','m')))
    
  10. str(('a','b','c'))
    
  11. "".join(('a','b','c'))
    

Operators

The following operators work on tuples and behave exactly as in lists:

Operator

Result

Meaning

len(tuple)

int

Return the length of a tuple

tuple[int]

object

Reads an element at specified index

tuple[int:int]

tuple

Extracts a sub-tuple - return a NEW tuple

tuple + tuple

tuple

Concatenates two tuples - return a NEW tuple

obj in tuple

bool

Checks whether an element is present in a tuple

tuple * int

tuple

Replicates the tuple - return a NEW tuple

==,!=

bool

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)

  1. len(3,2,4)
    
  2. len((3,2,4))
    
  3. len(('a',))
    
  4. len(('a,'))
    
  5. len(((),(),()))
    
  6. len(len((1,2,3,4)))
    
  7. 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. (1,2,3)[0]
    
  2. (1,2,3)[3]
    
  3. (1,2,3)0
    
  4. ('a,')[0]
    
  5. ('a',)[0]
    
  6. (1,2,3)[-0]
    
  7. (1,2,3)[-1]
    
  8. (1,2,3)[-3]
    
  9. ()[0]
    
  10. (())[0]
    
  11. type((())[0])
    
[ ]:

Exercise - animals

Given the string animals = "Siamese cat,dog,canary,piglet,rabbit,hamster"

  1. convert it to a list

  2. create a tuple of tuples where each tuple has two elements: the animal name and the name length, i.e. ((“dog”,3), ( “hamster”,7))

  3. 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

Show solution
[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)

  1. (7,6,8,9,5)(1:3)
    
  2. (7,6,8,9,5)[1:3]
    
  3. (10,11,12,13,14,15,16)[3:100]
    
  4. (10,11,12,13,14,15,16)[-3:5]
    
  5. (1,0,1,0,1,0)[::2]
    
  6. (1,2,3)[::1]
    
  7. (1,0,1,0,1,0)[1::2]
    
  8. tuple("postcards")[0::2]
    
  9. (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)

  1. (2,3,4) + tuple([5,6,7])
    
  2. "crazy"+('r','o','c','k','e','t')
    
  3. ()+()
    
  4. type(()+())
    
  5. len(()+())
    
  6. ()+[]
    
  7. []+()
    

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)

  1. 3 in (1.0, 2.0,3.0)
    
  2. 3.0 in (1,2,3)
    
  3. 3 not in (3)
    
  4. 3 not in (3,)
    
  5. 6 not in ()
    
  6. 0 in (0)[0]
    
  7. [] in ()
    
  8. () in []
    
  9. not [] in ()
    
  10. () in ()
    
  11. () in (())
    
  12. () in ((),)
    
  13. '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:

[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)

  1. (5,6,7)*(3.0)
    
  2. (5,6,7)*(3,0)
    
  3. (5,6,7)*(3)
    
  4. (5,6,7)*3
    
  5. (4,2,3)*int(3.0)
    
  6. (1,2)*[3][0]
    
  7. (1,2)*(3,4)[-1]
    
  8. [(9,8)]*4
    
  9. (1+2,3+4)*5
    
  10. (1+2,)*4
    
  11. (1+2)*4
    
  12. (1,2,3)*0
    
  13. (7)*0
    
  14. (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')
Show solution
[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 one

  • at 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')
Show solution
[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')
Show solution
[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)
Show solution
[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

Return

Description

tuple.index(obj)

int

Searches for the first occurence of an element and returns its position

tuple.count(obj)

int

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:

  1. Could the tuple contain duplicates? Remember only the first will be found!

  2. Could the tuple not contain the searched element? Remember to also handle this case!

  3. 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?

  4. 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 write my_tuple[3] == element. If you used index, 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)

  1. (3,4,2).index(4)
    
  2. (3,4,---1).index(-1)
    
  3. (2.2,.2,2,).index(2)
    
  4. (3,4,2).index(len([3,8,2,9]))
    
  5. (6,6,6).index(666)
    
  6. (4,2,3).index(3).index(3)
    
  7. tuple("GUG").index("g")
    
  8. (tuple("ci") + ("a","o")).index('a')
    
  9. (()).index(())
    
  10. ((),).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
Show solution
[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:

  1. Could the tuple contain duplicates? Remember only the first will be found!

  2. Could the tuple not contain the element to count? Remember to also handle this case!

  3. 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)

  1. ('p', 'o', 'r', 't', 'e', 'n', 't', 'o', 's', 'o').count('o')
    
  2. ('p', 'o', 'r', 't', 'e', 'n', 't', 'o', 's', 'o').count( ('o') )
    
  3. ('p', 'o', 'r', 't', 'e', 'n', 't', 'o', 's', 'o').count( ('o',) )
    
  4. (1,0,0,0).count( 0 )
    
  5. (1,0,0,0).count( (0) )
    
  6. (1,0,0,0).count( (0,) )
    
  7. (1,0,(0,),(0,)).count( (0,) )
    
  8. (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.

  1. How many elements must the list have?

  2. 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.

  1. 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
Show solution
[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