Lists 2 - operators

Download exercises zip

Browse online files

There are several operators to manipulate lists. The following ones behave like the ones we’ve seen in strings:

Operator

Result

Meaning

len(lst)

int

Return the list length

list[int]

obj

Reads/writes an element at the specified index

list[int:int]

list

Extracts a sublist - return a NEW list

obj in list

bool

Cheks if the element is contained in the list

list + list

list

Concatenates two lists - return a NEW list

max(lst)

int

Given a list of numbers, return the greatest one

min(lst)

int

Given a list of numbers, returns the smallest one

sum(lst)

int

Given a list of numbers, sums all of them

list * int

list

Replicates the list - return a NEW list

==,!=

bool

Cheks whether lists are equal of different

What to do

  1. Unzip exercises zip in a folder, you should obtain something like this:

lists
    lists1.ipynb
    lists1-sol.ipynb
    lists2.ipynb
    lists2-sol.ipynb
    lists3.ipynb
    lists3-sol.ipynb
    lists4.ipynb
    lists4-sol.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 lists2.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. 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

Length of a list

A list is a sequence, and like any sequence you can use the function len to obtain the length:

[2]:
a = [7,5,8]
[3]:
len(a)
[3]:
3
[4]:
b = [8,3,6,4,7]
[5]:
len(b)
[5]:
5

If a list contains other lists, they count as single elements:

[6]:
mixed = [
            [4,5,1],
            [8,6],
            [7,6,0,8],
        ]
[7]:
len(mixed)
[7]:
3

WARNING: YOU CAN’T use len as a method

For example, this DOESN’T work: [3,4,2].len()

EXERCISE: Try writing [3,4,2].len() here, which error appears?

Show solution
[8]:
# write here


EXERCISE: Try writing [3,4,2].len WITHOUT the round parenthesis at the end, which error appears?

Show solution
[9]:
# write here


QUESTION: If x is some list, by writing:

len(len(x))

what do we get?

  1. the length of the list

  2. an error

  3. something else

Show answerShow solution
[10]:
# write here


QUESTION: Look at this expression, without executing it. What does it produce?

[len([]), len([len(['a','b'])])]
  1. an error (which one?)

  2. a number (which one?)

  3. a list (which one?)

Try writing the result by hand, and then compare it with the one obtained by executing the code in a cell.

Show answer

QUESTION: Look at this expression, without executing it. What does it produce?

len([[[],[]],[],[[[]]],[[],[]]])
  1. an error (which one?)

  2. a number (which one?)

  3. a list (which one?)

Show answer

QUESTION: What does the following expression produce?

[[((len('ababb')))],len(["argg",('b'),("c")]), len([len("bc")])]
Show answer

Reading an element

Like for strings, we can access an element a list element by putting the index of the position we want to access among square brackets:

[11]:
    # 0   1   2   3
la = [77, 69, 95, 57]

As for any sequence, the positions start from 0:

[12]:
la[0]
[12]:
77
[13]:
la[1]
[13]:
69
[14]:
la[2]
[14]:
95
[15]:
la[3]
[15]:
57

Like for any string, if we exaggerate with the index we get an error:

la[4]

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-134-09bfed834fa2> in <module>
----> 1 la[4]

IndexError: list index out of range

As in strings, we can obtain last element by using a negative index:

[16]:
    # 0   1   2   3
la = [77, 69, 95, 57]
[17]:
la[-1]
[17]:
57
[18]:
la[-2]
[18]:
95
[19]:
la[-3]
[19]:
69
[20]:
la[-4]
[20]:
77

If we go beyond the list length, we get an error:

la[-5]

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-169-f77280923dce> in <module>
----> 1 la[-5]

IndexError: list index out of range

QUESTION: if x is some list, by writing:

x[0]

what do we get?

  1. the first element of the list

  2. always an error

  3. sometimes an element, sometimes an error according to the list

Show answer
[ ]:

QUESTION: if x is some list, by writing:

x[len(x)]

what do we get?

  1. an element of the list

  2. always an error

  3. sometimes an element, sometimes an error according to the list

Show answer

Writing an element

Since all the lists are MUTABLE, given a list object we can change the content of any cell inside.

For example, suppose you want to change the cell at index 2 of the list la, from 6 to 5:

[21]:
     #0  1  2  3
la = [7, 9, 6, 8]

We might write like this:

[22]:
la[2] = 5

[23]:
la
[23]:
[7, 9, 5, 8]

Let’s see what’s happening with Python Tutor:

[24]:
# WARNING: FOR PYTHON TUTOR TO WORT, REMEMBER TO EXECUTE THIS CELL with Shift+Enter
#          (it's sufficient to execute it only once)


import jupman
[25]:
#     0  1  2  3
la = [7, 9, 6, 8]
la[2] = 5

jupman.pytut()
[25]:

As you see, no new memory regions are created, it just overwrites an existing cell.

Mutating shared lists

WARNING: 90% OF PROGRAMMING ERRORS ARE CAUSED BY MISUNDERSTANDING THIS TOPIC !!!

READ VERY WELL !!!

What happens when we associate the same identical mutable object to two variables, like for example a list, and then we mutate the object using one of the two variables?

Let’s look at an example - first, we associate the list [7,9,6] to variable la:

[26]:
la = [7,9,6]

Now we define a new variable lb, and we associate the same value that was already associated to variable la. Note: we are NOT creating new lists !

[27]:
lb = la
[28]:
print(la)  # la is always the same
[7, 9, 6]
[29]:
print(lb)  # lb is the *same* list associated to la
[7, 9, 6]

We can now try modifying a cell of lb, putting 5 in the cell at index 0:

[30]:
lb[0] = 5

If we try printing the variables la and lb, Python will look at the values associated to each variable. Since the value is the same identical list (which is in the same identical memory region), in both cases you will see the change we just did !

[31]:
print(la)
[5, 9, 6]
[32]:
print(lb)
[5, 9, 6]

Let’s see in detail what happens with Python Tutor:

[33]:
la = [7,9,6]
lb = la
lb[0] = 5
print('la è', la)
print('lb è', lb)

jupman.pytut()
la è [5, 9, 6]
lb è [5, 9, 6]
[33]:

Let’s see the difference when we explicitly create a list equal to la.

In this case we will have two distinct memory regions and la will NOT be modified:

[34]:
la = [7,9,6]
lb = [7,9,6]
lb[0] = 5
print('la is', la)
print('lb is', lb)

jupman.pytut()
la is [7, 9, 6]
lb is [5, 9, 6]
[34]:

QUESTION: After executing this code, what will be printed? How many lists will be present in memory?

Try drawing ON PAPER what is supposed to happen in memory, and then compare with Python Tutor!

la = [8,7,7]
lb = [9,6,7,5]
lc = lb
la = lb
print('la è', la)
print('lb è', lb)
print('lc è', lc)
Show answer
[35]:
la = [8,7,7]
lb = [9,6,7,5]
lc = lb
la = lb
#print('la è', la)
#print('lb è', lb)
#print('lc è', lc)
jupman.pytut()
[35]:

QUESTION: Look at the following code. After its execution, by printing la, lb and lc what will we get?

Try drawing ON PAPER what is happening in memory, then compare the result with Python Tutor!

la = [7,8,5]
lb = [6,7]
lc = lb
lb = la
lc[0] = 9
print('la is', la)
print('lb is', lb)
print('lc is', lc)
Show answer
[36]:
la = [7,8,5]
lb = [6,7]
lc = lb
lb = la
lc[0] = 9
#print('la è', la)
#print('lb è', lb)
#print('lc è', lc)

jupman.pytut()
[36]:

Slices

We can extract sequences from lists by using slices. A slice is produced by placing square brackets after the list with inside the starting index (INCLUDED), followed by a colon :, followed by the end index (EXCLUDED). It works exactly as with strings: in that case the slice produces a new string, in this case it produces a NEW list. Let’s see an example:

[37]:
     #0  1  2  3  4  5  6  7  8  9
la = [43,35,82,75,93,12,43,28,54,65]
[38]:
la[3:7]
[38]:
[75, 93, 12, 43]

We extracted a NEW list [75, 93, 12, 43] from the list la starting from index 3 INCLUDED until index 7 EXCLUDED. We can see the original list is preserved:

[39]:
la
[39]:
[43, 35, 82, 75, 93, 12, 43, 28, 54, 65]

Let’s verify what happens with Python Tutor, by assigning the new list to a variable lb:

[40]:
#     0  1  2  3  4  5  6  7  8  9
la = [43,35,82,75,93,12,43,28,54,65]
lb = la[3:7]

jupman.pytut()
[40]:

You will notice a NEW memory region, associated to variable lb.

Slice - limits

When we operate with slices we must be careful about indeces limits. Let’s see how they behave:

[41]:
#0  1  2  3  4
[58,97,76,87,99][0:3]  # from index 0 *included* to 3 *excluded*
[41]:
[58, 97, 76]
[42]:
#0  1  2  3  4
[58,97,76,87,99][0:4]  # from index 0 *included* a 4 *excluded*
[42]:
[58, 97, 76, 87]
[43]:
#0  1  2  3  4
[58,97,76,87,99][0:5]  # from index 0 *included* to 5 *excluded*
[43]:
[58, 97, 76, 87, 99]
[44]:
#0  1  2  3  4
[58,97,76,87,99][0:6]   # if we go beyond the list length Python does not complain
[44]:
[58, 97, 76, 87, 99]
[45]:
#0  1  2  3  4
[58,97,76,87,99][8:12] # Python doesn't complain even if we start from non-existing indeces
[45]:
[]

QUESTION: This expression:

[][3:8]
  1. produces a result (which one?)

  2. produces an error (which one?)

Show answer

QUESTION: if x is some list (may also empty), what does this expression do? Can it give an error? Does it return something useful?

x[0:len(x)]
Show answer

Slices - omitting limits

If we will, it is possible to omit start index, in which case Python will suppose it’s 0:

[46]:
#0  1  2  3  4  5  6  7  8  9
[98,67,85,77,65,99,67,55,79][:3]
[46]:
[98, 67, 85]

It is also possible to omit the end index, in this case Python will extract elements until the list end:

[47]:
#0  1  2  3  4  5  6  7  8  9
[98,67,85,77,65,99,67,55,79][3:]
[47]:
[77, 65, 99, 67, 55, 79]

By omitting both indexes we obtain the full list:

[48]:
#0  1  2  3  4  5  6  7  8  9
[98,67,85,77,65,99,67,55,79][:]
[48]:
[98, 67, 85, 77, 65, 99, 67, 55, 79]

QUESTION: What is this code going to print? Will la get modified or not?

la = [7,8,9]
lb = la[:]
lb[0] = 6
print('la =',la)
print('lb =',lb)
Show answer
[49]:
la = [7,8,9]
lb = la[:]
lb[0] = 6
#print('la =',la)
#print('lb =',lb)

jupman.pytut()
[49]:

QUESTION: For each of the following expressions, try guessing which value it produces, or if it gives an error.

  1. [9,7,8,6][1:1]
    
  2. [9,7,8,6][1:2]
    
  3. [9,7,8,6][2:3][0]
    
  4. [][]
    
  5. [][:]
    
  6. [3][:]
    
  7. [:][]
    

Slices - negative limits

It is also possible to set inverse and negative limits, although it is not always intuitive:

[50]:
#0  1  2  3  4  5  6
[73,48,19,57,64,15,92][3:0]   # from index 3 to positive indexes <= 3 produces nothing
[50]:
[]
[51]:
#0  1  2  3  4  5  6
[73,48,19,57,64,15,92][3:1]   # from index 3 to positive indexes <= 3 produces nothing
[51]:
[]
[52]:
#0  1  2  3  4  5  6
[73,48,19,57,64,15,92][3:2]   # from index 3 to positive indexes <= 3 produces nothing
[52]:
[]
[53]:
#0  1  2  3  4  5  6
[73,48,19,57,64,15,92][3:3]   # from index 3 to positive indexes <= 3 produces nothing
[53]:
[]

Let’s see what happens with negative indexes:

[54]:
# 0  1  2  3  4  5  6
#-7 -6 -5 -4 -3 -2 -1
[73,48,19,57,64,15,92][3:-1]
[54]:
[57, 64, 15]
[55]:
# 0  1  2  3  4  5  6
#-7 -6 -5 -4 -3 -2 -1
[73,48,19,57,64,15,92][3:-2]
[55]:
[57, 64]
[56]:
# 0  1  2  3  4  5  6
#-7 -6 -5 -4 -3 -2 -1
[73,48,19,57,64,15,92][3:-3]
[56]:
[57]
[57]:
# 0  1  2  3  4  5  6
#-7 -6 -5 -4 -3 -2 -1
[73,48,19,57,64,15,92][3:-4]
[57]:
[]
[58]:
# 0  1  2  3  4  5  6
#-7 -6 -5 -4 -3 -2 -1
[73,48,19,57,64,15,92][3:-5]
[58]:
[]

It is also possible to start from a negative index and arrive to a positive one. As long as the first index marks a position which precedes the second index, something gets returned:

[59]:
# 0  1  2  3  4  5  6
#-7 -6 -5 -4 -3 -2 -1
[73,48,19,57,64,15,92][-7:3]
[59]:
[73, 48, 19]
[60]:
# 0  1  2  3  4  5  6
#-7 -6 -5 -4 -3 -2 -1
[73,48,19,57,64,15,92][-6:3]
[60]:
[48, 19]
[61]:
# 0  1  2  3  4  5  6
#-7 -6 -5 -4 -3 -2 -1
[73,48,19,57,64,15,92][-5:3]
[61]:
[19]
[62]:
# 0  1  2  3  4  5  6
#-7 -6 -5 -4 -3 -2 -1
[73,48,19,57,64,15,92][-4:3]
[62]:
[]
[63]:
# 0  1  2  3  4  5  6
#-7 -6 -5 -4 -3 -2 -1
[73,48,19,57,64,15,92][-3:3]
[63]:
[]
[64]:
# 0  1  2  3  4  5  6
#-7 -6 -5 -4 -3 -2 -1
[73,48,19,57,64,15,92][-2:3]
[64]:
[]

QUESTION: For each of the following expressions, try guessing which value is produced, or if it gives an error

  1. [9,7,8,6][0:-2]
    
  2. [0:-2][9,7,8,6]
    
  3. [5,7,9][1:-1]
    
  4. [][-13:-17]
    
  5. [9,7,8,6][-4:-1]
    
  6. [9,7,8,6][-5:-1]
    
  7. [9,7,8,6,10,32][-3:1]
    
  8. [9,7,8,6,10,32][-3:5]
    

Slices - modifying

Suppose we have the list

[65]:
    # 0  1  2  3  4  5  6  7
la = [12,23,35,41,74,65,34,22]

and we want to change la cells from index 3 INCLUDED to index 6 EXCLUDED in such a way they contain the numbers taken from list [98,96,97]. We can do it with this special notation which allows us to write a slice to the left of operator =:

[66]:
la[3:6] = [98,96,97]
[67]:
la
[67]:
[12, 23, 35, 98, 96, 97, 34, 22]

In this slightly more complex example we verify in Python Tutor that the original memory region gets actually modifyied:

[68]:
#     0  1  2  3  4  5  6  7
la = [12,23,35,41,74,65,34,22]
lb = la
lb[3:6] = [98,96,97]

jupman.pytut()
[68]:

QUESTION: Look at the following code - what does it produce?

la = [9,6,5,8,2]
la[1:4] = [4,7,0]
print(la)
  1. modify la (how?)

  2. an error (which one?)

Show answer

QUESTION: Look at the following code. What does it produce?

la = [7,6,8,4,2,4,2,3,1]
i = 3
lb = la[0:i]
la[i:2*i] = lb
print(la)
  1. modifies la (how?)

  2. an error (which one?)

Show answer

List of strings

We said we can put any object into a list, for example some strings:

[69]:
vegetables = ['tomatoes', 'onions', 'carrots', 'cabbage']

Let’s try extracting a vegetable by writing this expression:

[70]:
vegetables[2]
[70]:
'carrots'

Now, the preceding expression produces the result 'carrots', which we know is a string. This suggests we can use the expression exactly like if it were a string.

Suppose we want to obtain the first character of the string 'carrots', if we directly have the string we can write like this:

[71]:
'carrots'[0]
[71]:
'c'

But if the string is inside the previous list, we could directly do like this:

[72]:
vegetables[2][0]
[72]:
'c'

Exercise - province codes

Given a list with exactly 4 province codes in lowercase, write some code which creates a NEW list containing the same codes in uppercase characters.

  • your code must work with any list of 4 provinces

  • hint: if you don’t remember the right method, have a look here

Example 1 - given:

provinces = ['tn','mi','to','ro']

your code must print:

['TN', 'MI', 'TO', 'RO']

Example 2 - given:

provinces = ['pa','ge','ve', 'aq']

Your code must print:

['PA', 'GE', 'VE', 'AQ']
Show solution
[73]:
provinces = ['tn','mi','to','ro']
#provinces = ['pa','ge','ve', 'aq']

# write here


Exercise - games

Given a list games of exactly 3 strings, write some code which MODIFIES the list so it contains only the first characters of each string.

  • Your code must work with any list of exactly 3 strings

Example - given

games = ["Monopoly",
         "RISK",
         "Bingo"]

After executing the code, it must result:

>>> print(games)
["M","R","B"]
Show solution
[74]:
games = ["Monopoly",
         "RISK",
         "Bingo"]


# write here


List of lists

NOTE: We will talk much more in detail of lists of lists in the tutorial Matrices - list of lists, this is just a brief introduction.

The consideration we’ve seen so far about string lists are also valid for a list of lists:

[75]:
couples = [             # external list
            [67,95],    # internal list at index 0
            [60,59],    # internal list at index 1
            [86,75],    # internal list at index 2
            [96,90],    # internal list at index 3
            [88,87],    # internal list at index 4
          ]

If we want ot extract the number 90, we must first extract the sublist from index 3:

[76]:
couples[3]   # NOTE: the expression result is a list
[76]:
[96, 90]

and so in the extracted sublist (which has only two elements) we can recover the number at index 0:

[77]:
couples[3][0]
[77]:
96

and at index 1:

[78]:
couples[3][1]
[78]:
90

Exercise - couples

  1. Write some code to extract and print the number 86, 67 and 87

  2. Given a row with index i and a column j, print the number at row i and column j multiplied by the number at successive row and same column

After your code, you should see printed

point 1: 86 67 87

point 2:  i = 3  j = 1  result = 7830
Show solution
[79]:
couples = [             # external list
            [67,95],    # internal list at index 0
            [60,59],    # internal list at index 1
            [86,75],    # internal list at index 2
            [96,90],    # internal list at index 3
            [88,87],    # internal list at index 4
          ]

i = 3
j = 1

# write here


point 1: 86 67 87

point 2:  i = 3  j = 1  result = 7830

Exercise - nonunif

Given a list nonunif of sublists of any length, and a row at index i, write some code which MODIFIES the sublists of nonunif at row i and successive one in such a way the last element of both lists becomes 99.

  • your code must work with any nonunif and any i

Example 1 - given:

nonunif = [                   # external list
            [67,95],          # internal at index 0
            [60,23,23,13,59], # internal at index 1
            [86,75],          # internal at index 2
            [96,90,92],       # internal at index 3
            [88,87],          # internal at index 4
         ]

i = 1

after your code, by writing (we use pprint because it will print on many lines)

from pprint import pprint
pprint(nonunif,width=30)

it should print:

[[67, 95],
 [60, 23, 23, 13, 99],
 [86, 99],
 [96, 90, 92],
 [88, 87]]
Show solution
[80]:
nonunif = [                   # external list
            [67,95],          # internal list at index 0
            [60,23,23,13,59], # internal list at index 1
            [86,75],          # internal list at index 2
            [96,90,92],       # internal list at index 3
            [88,87],          # internal list at index 4
         ]

i = 1

# write here


[[67, 95],
 [60, 23, 23, 13, 99],
 [86, 99],
 [96, 90, 92],
 [88, 87]]

in operator

To verify whether an object is contained in a list, we can use the in operator.

Note the result of this expression is a boolean:

[81]:
9 in [6,8,9,7]
[81]:
True
[82]:
5 in [6,8,9,7]
[82]:
False
[83]:
"apple" in ["watermelon","apple","banana"]
[83]:
True
[84]:
"carrot" in ["watermelon","apple","banana"]
[84]:
False

QUESTION: What’s the result of this expression? True or False?

True in [ 5 in [6,7,5],
          2 in [8,1]
        ]
Show answer

not in

We can write the check of non belonging in two ways:

Way 1:

[85]:
"carrot" not in ["watermelon","banana","apple"]
[85]:
True
[86]:
"watermelon" not in ["watermelon","banana","apple"]
[86]:
False

Way 2:

[87]:
not "carrot" in ["watermelon","banana","apple"]
[87]:
True
[88]:
not "watermelon" in ["watermelon","banana","apple"]
[88]:
False

QUESTION: Given any element x and list y, what does the following expression produce?

x in y and not x in y
  1. False

  2. True

  3. False or True according to the values of x and y

  4. an error

Show answer

QUESTION: For each of the following expressions, try to guess the result

  1. 3 in [3]
    
  2. [4,5] in [1,2,3,4,5]
    
  3. [4,5] in [[1,2,3],[4,5]]
    
  4. [4,5] in [[1,2,3,4],[5,6]]
    
  5. 'n' in ['alien'[-1]]
    
  6. 'rts' in 'karts'[1:4]
    
  7. [] in [[[]]]
    
  8. [] in [[]]
    
  9. [] in ["[]"]
    

QUESTION: For each of the following expressions, independently from the value of x, tell whether it always results True:

  1. x in x
    
  2. x in [x]
    
  3. x not in []
    
  4. x in [[x]]
    
  5. x in [[x][0]]
    
  6. (x and y) in [x,y]
    
  7. x in [x,y] and y in [x,y]
    

Exercise - vegetables

Given the list vegetables of exactly 5 strings and the list of strings fruits, MODIFY the variable vegetables so that in each cell there is True if the vegetable is a fruit or False otherwise.

  • your code must work with any list of 5 strings vegetables and any list fruits

Example - given:

vegetables = ["carrot",
              "cabbage",
              "apple",
              "aubergine",
              "watermelon"]

fruits = ["watermelon","banana","apple",]

after execution your code must print:

>>> print(vegetables)
[False, False, True, False, True]
Show solution
[89]:
vegetables = ["carrot",
              "cabbage",
              "apple",
              "aubergine",
              "watermelon"]

fruits = ["watermelon","banana","apple",]

# write here


List concatenation with +

Given two lists la and lb, we can concatenate them with the operator + which produces a NEW list:

[90]:
la = [77,66,88]
lb = [99,55]

la + lb
[90]:
[77, 66, 88, 99, 55]

Note the operator + produces a NEW list, so la and lb remained unchanged:

[91]:
print(la)
[77, 66, 88]
[92]:
print(lb)
[99, 55]

Let’s check with Python Tutor:

[93]:
la = [77,66,88]
lb = [99,55]
lc = la + lb

print(la)
print(lb)
print(lc)

jupman.pytut()
[77, 66, 88]
[99, 55]
[77, 66, 88, 99, 55]
[93]:

Exercise - concatenation

Write some code which given lists la and lb, puts into list lc the last two elements of la and the first two of lb

Example - given:

la = [18,26,30,45,55]
lb = [16,26,37,45]

after your code it must print:

>>> print(la)
[18, 26, 30, 45, 55]
>>> print(lb)
[16, 26, 37, 45]
>>> print(lc)
[45, 55, 37, 45]
Show solution
[94]:
la = [18,26,30,45,55]
lb = [16,26,37,45]

# write here


QUESTION: For each of the following expressions, try guessing the result

  1. [6,7,8] + [9]
    
  2. [6,7,8] + []
    
  3. [] + [6,7,8]
    
  4. [] + []
    
  5. [] + [[]]
    
  6. [[]]+[]
    
  7. [[]]+[[]]
    
  8. ([6] + [8])[0]
    
  9. ([6] + [8])[1]
    
  10. ([6] + [8])[2:]
    
  11. len([4,2,5])+len([3,1,2])
    
  12. len([4,2,5] + [3,1,2])
    
  13. [5,4,3] + "3,1"
    
  14. [5,4,3] + "[3,1]"
    
  15. "[5,4,3]" + "[3,1]"
    
  16. ["4","1","7"] + ["3","1"]
    
  17. list('coca') + ['c','o','l','a']
    

min and max

A list is a sequence of elements, and as such we can pass it to functions min or max for finding respectively the minimum or the maximum element of the list.

[95]:
min([4,5,3,7,8,6])
[95]:
3
[96]:
max([4,5,3,7,8,6])
[96]:
8

V COMMANDMENT : You shall never ever use min and max as variable names.

(adapted) If you do, you will lose the functions!

Note it’s also possible to directly pass to min and max the elements to compare without including them in a list:

[97]:
min(4,5,3,7,8,6)
[97]:
3
[98]:
max(4,5,3,7,8,6)
[98]:
8

But if we pass only one, without including it in a list, we will get an error:

min(4)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-156-bb3db472b52e> in <module>
----> 1 min(4)

TypeError: 'int' object is not iterable

The error tells us that when we pass only an argument, Python expects a sequence like a list:

[99]:
min([4])
[99]:
4

To min and max we can also pass strings, and we will get the character which is alphabetically lesser or greater:

[100]:
min("orchestra")
[100]:
'a'
[101]:
max("orchestra")
[101]:
't'

If we pass a list of strings, we will obtain the lesser or greater string in lexicographical order (i.e. the phonebook order)

[102]:
min(['the', 'sailor', 'walks', 'around', 'the', 'docks'])
[102]:
'around'
[103]:
max(['the', 'sailor', 'walks', 'around', 'the', 'docks'])
[103]:
'walks'

QUESTION: For each of the following expressions, try guessing the result (or if it gives an error)

  1. max(7)
    
  2. max([7])
    
  3. max([5,4,6,2])
    
  4. max([min([7,3])])
    
  5. max([])
    
  6. max(2,9,3)
    
  7. max([3,2,5] + [9,2,3])
    
  8. max(max([3,2,5], max([9,2,3]))
    
  9. max(min(3,6), min(8,2))
    
  10. min(max(3,6), max(8,2))
    
  11. max(['a','b','d','c'])
    
  12. max(['barca', 'dado', 'aloa', 'cerchio'])
    
  13. min(['prova','','z','v'])
    
  14. max(['martello'[-1],'cacciavite'[-1],'brugola'[-1]])
    
  15. min(['martello'[-1],'cacciavite'[-1],'brugola'[-1]])
    

sum

With sum we can sum all the elements in a list:

[104]:
sum([1,2,3])
[104]:
6
[105]:
sum([1.0, 2.0, 0.14])
[105]:
3.14

V COMMANDMENT : You shall never ever use sum as a variable name

(adapted) If you do, you will lose the function!

QUESTION: For each of the following expressions, try guessing the result (or if it gives an error):

  1. sum[3,1,2]
    
  2. sum(1,2,3)
    
  3. la = [1,2,3]
    sum(la) > max(la)
    
  4. la = [1,2,3]
    sum(la) > max(la)*len(la)
    
  5. la = [4,2,6,4,7]
    lb = [max(la), min(la), max(la)]
    print(max(lb) != max(la))
    

Exercise - balance

Given a list of n numbers balance with n even, write some code which prints True if the sum of all first n/2 numbers is equal to the sum of all successive ones.

  • your code must work for any number list

Example 1 - given:

balance = [4,3,7,1,5,8]

after your code, it must print:

True

Example 2 - given:

balance = [4,3,3,1,9,8]

after your code, it must print:

False
Show solution
[106]:
balance = [4,3,7,1,5,8]
#bilancia = [4,3,3,1,9,8]

# write here


[106]:
True

Multiplying lists

To replicate the elements of a list, it’s possible to use the operator * which produces a NEW list:

[107]:
[7,6,8] * 2
[107]:
[7, 6, 8, 7, 6, 8]
[108]:
[7,6,8] * 3
[108]:
[7, 6, 8, 7, 6, 8, 7, 6, 8]

Note a NEW list is produced, and the original one is not modified:

[109]:
la = [7,6,8]
[110]:
lb = [7,6,8] * 3
[111]:
la   # original
[111]:
[7, 6, 8]
[112]:
lb   # expression result
[112]:
[7, 6, 8, 7, 6, 8, 7, 6, 8]

We can multiply a list of strings:

[113]:
la = ["a", "world", "of", "words"]
[114]:
lb = la * 2
[115]:
print(la)
['a', 'world', 'of', 'words']
[116]:
print(lb)
['a', 'world', 'of', 'words', 'a', 'world', 'of', 'words']

As long as we multiply lists which contain immutable elements like numbers or strings, no particular problems arise:

[117]:
la = ["a", "world", "of", "words"]
lb = la * 2

jupman.pytut()
[117]:

The matter becomes much more sophisticated when we multiply lists which contain mutable objects like other lists. Let’s see an example:

[118]:
la = [5,6]
lb = [7,8,9]
lc = [la,lb] * 2
[119]:
print(la)
[5, 6]
[120]:
print(lb)
[7, 8, 9]
[121]:
print(lc)
[[5, 6], [7, 8, 9], [5, 6], [7, 8, 9]]

By printing it, we see that the lists la and lb are represented inside lc - but how, exactly? print calls may trick you about the effective state of memory - to investigate further it’s convenient to use Python Tutor:

[122]:
la = [5,6]
lb = [7,8,9]
lc = [la,lb] * 2

jupman.pytut()
[122]:

Arggh ! A jungle of arrows will appear ! This happens because when we write [la, lb] we create a list with two references to other lists [5,6] and [7,8,9], and the operator * when duplicating it just copies references.

For now we stop here, we will see the implications details later in the tutorial matrices - lists of lists

Equality

We can check whether two lists are equal with equality operator ==, which given two lists returns True if they contain equal elements or False otherwise:

[123]:
[4,3,6] == [4,3,6]
[123]:
True
[124]:
[4,3,6] == [4,3]
[124]:
False
[125]:
[4,3,6] == [4,3,6, 'ciao']
[125]:
False
[126]:
[4,3,6] == [2,2,8]
[126]:
False

We can check equality of lists with heterogenous elements:

[127]:
['apples', 3, ['cherries', 2], 6] == ['apples', 3, ['cherries', 2], 6]
[127]:
True
[128]:
['bananas', 3,['cherries', 2], 6] == ['apples', 3, ['cherries', 2], 6]
[128]:
False

To check for inequality, we can use the operatpr !=:

[129]:
[2,2,8] != [2,2,8]
[129]:
False
[130]:
[4,6,0] != [2,2,8]
[130]:
True
[131]:
[4,6,0] != [4,6,0,2]
[131]:
True

QUESTION: For each of the following expressions, guess whether it is True, False or it produces an error:

  1. [2,3,1] != [2,3,1]
    
  2. [4,8,12] == [2*2,4*2,6*2]
    
  3. [7,8][:] == [7,9-1]
    
  4. [7][0] == [[7]][0]
    
  5. [9] == [9][0]
    
  6. [max(7,9)] == [max([7]),max([9])]
    
  7. ['a','b','c'] == ['A','B','C']
    
  8. ['a','b'] != ['a','b','c']
    
  9. ["ciao"] != ["CIAO".lower()]
    
  10. [True in [True]] != [False]
    
  11. [][:] == []
    
  12. [[]] == [] + []
    
  13. [[],[]] == [] + []
    
  14. [[[]]] == [[[]+[]]]
    

Continue

You can find more exercise in the notebook Lists 3

[ ]: