Lists 3 - Basic methods
Download exercises zip
Lists are objects of type list
and have several methods for performing operations on them, let’s see the basic ones:
Method |
Returns |
Description |
---|---|---|
|
Adds a new element at the end of the list |
|
|
Adds many elements at the end of the list |
|
|
Adds a new element into some given position |
|
|
Removes and return the element at last position |
|
|
Given an index, removes and return the element at that position |
|
|
Inverts the order of elements |
|
|
Sorts the elements in-place |
|
|
produces a string concatenating all the elements in seq separated by |
|
|
Copia superficialmente la list |
The others are described at the page Search methods
WARNING 1: LIST METHODS *MODIFY* THE LIST ON WHICH ARE CALLED !
Whenever you call a method of a list (the object to the left of the dot .
), you MODIFY the list itself (differently from string methods which always generate a new string without changing the original)
WARNING 2: LIST METHODS RETURN NOTHING!
They almost always return the object None
(differently from strings which always return a new string)
What to do
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
lists5-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
lists3.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
append
method
We can MODIFY a list adding a single element at a time with the method append
.
Suppose to start from an empty list:
[2]:
la = []
If we want to add as element the number 50
, we can write like this:
[3]:
la.append(50)
Note the list we initalilly created got MODIFIED:
[4]:
la
[4]:
[50]
WARNING: la.append(50)
returned NOTHING !!!!
Observe carefully the output of cell with instruction la.append(50)
, you will notice there is absolutely nothing. This happens because the purpose of append
is to MODIFY the list on which it is called, NOT generating new lists.
We append another number at the end of the list:
[5]:
la.append(90)
[6]:
la
[6]:
[50, 90]
[7]:
la.append(70)
[8]:
la
[8]:
[50, 90, 70]
Let’s see what happened in Python Tutor:
[9]:
# WARNING: FOR PYTHON TUTOR TO WORK, REMEMBER TO EXECUTE THIS CELL with Shift+Enter
# (it's sufficient to execute it only once)
import jupman
[10]:
la = []
la.append(50)
la.append(90)
la.append(70)
jupman.pytut()
[10]:
Note there is only one yellow memory region associated to variable la
which gets expanded as you click on Next.
We said append
method returns nothing, let’s try to add some detail. In the methods table, there is present a column named Returns. If you check it, for almost all methods included append
there is indicated it returns None
.
None
is the most boring object in Python, because it literally means nothing. What can you do with nothing? Very few things, so few that whenever Jupyter finds as result the None
object it doesn’t even print it. Try directly inserting None
in a cell, you will see it won’t be reported in cell output:
[11]:
None
A way to force the print is by using the command print
:
[12]:
print(None)
None
EXERCISE: What is the type of the object None
? Discover it by using the funciton type
[13]:
# write here
Let’s try repeating what happens with append
. If you call the method append
on a list, append
silently MODIFIES the list, and RETURNS the object None
as call result. Notice that Jupyter considers this object as non-interesting, so it doesn’t even print it.
Let’s try to get explicit about this misterious None
. If it’s true that append
produces it as call result, it means we can associate this result to some variable. Let’s try to associate it to variable x
:
[14]:
la = []
x = la.append(70)
Now, if everything went as we wrote, append
should have modified the list:
[15]:
la
[15]:
[70]
and there should be associated None
to variable x
. So, if we ask Jupyter to show the value associated to x
and that value is None
, nothing will appear:
[16]:
x
Note there is no output in the cell, apparently we are really in presence of a None
. Let’s force the print
:
[17]:
print(x)
None
Here it is! Probably you will be a little confused by all of this, so let’s check again what happens in Python Tutor:
[18]:
la = []
x = la.append(70)
print("la is", la)
print("x is", x)
jupman.pytut()
la is [70]
x is None
[18]:
What’s the final gist?
REUSING THE RESULT OF LIST METHODS CALLS IS ALMOST ALWAYS AN ERROR !
Since calling list methods returns None
, which is a ‘useless’ object, trying to reuse it will almost surely produce an error
EXERCISE: Build a list by adding one element at a time with the method append
. Add the elements 77
, "test"
, [60,93]
with three calls to append
, and finally print the list.
After your code, you should see [77, 'test', [60, 93]]
[19]:
la = []
# write here
QUESTION: The following code:
la = []
la.append(80,70,90)
produces an error (which one?)
modifies the list (how?)
QUESTION: The following code:
la = []
la.append(80).append(90)
produces an error
appends to
la
the numbers80
and90
QUESTION: let’s briefly go back to strings. Look at the following code (if you don’t remember what string methods do see here)
sa = ' trento '
sb = sa.strip().capitalize()
print(sb)
produces an error (which one?)
changes
sa
(how?)prints something (what?)
QUESTION: Have a look at this code. Will it print something at the end? Or will it produce an error?
la = []
lb = []
la.append(lb)
lb.append(90)
lb.append(70)
print(la)
Exercise - augmenting a list 1
Given the list la
of fixed dimension 7, write some code to augment the empty list lb
so to only contain the elements of la
with even index (0, 2, 4, …).
Your code should work with any list
la
of fixed dimension 7
# 0 1 2 3 4 5 6
la=[8,4,3,5,7,3,5]
lb=[]
After your code, you should obtain:
>>> print(lb)
[8,3,7,5]
[20]:
# 0 1 2 3 4 5 6
la=[8,4,3,5,7,3,5]
lb=[]
# write here
extend
method
We’ve seen that with append
we can augment a list one element at a time.
What if we wanted to add many elements in a single shot, maybe taken from another list?
We should use the method extend
, which MODIFIES the list on which it is called by adding all the elements it finds in the input sequence.
[21]:
la = [70,30,50]
[22]:
lb = [40,90,30,80]
[23]:
la.extend(lb)
[24]:
la
[24]:
[70, 30, 50, 40, 90, 30, 80]
[25]:
lb
[25]:
[40, 90, 30, 80]
In the example above, extend
is called on the variable la
, and we passed lb
as parameter
WARNING: la
is MODIFIED, but the sequence we passed in round parenthesis is not (lb
in the example)
QUESTION: the execution of method extend
returns something? What do you see in the output of cell la.extend(lb)
?
Let’s verify what happened with Python Tutor:
[26]:
la = [70,30,50]
lb = [40,90,30,80]
la.extend(lb)
jupman.pytut()
[26]:
QUESTION: Look inside this code. Which will be the values associated to variables la
,lb
and x
after its execution?
la = [30,70,50]
lb = [80,40]
x = la.extend(lb)
print('la is ', la)
print('lb is ', lb)
print('x is ', x)
Extending with sequences
We said that extend
can take any generic sequence in the round parenthesis, not only lists. This means we can also try to pass a string. For example:
[27]:
la = [70,60,80]
s = "hello"
la.extend(s)
[28]:
la
[28]:
[70, 60, 80, 'h', 'e', 'l', 'l', 'o']
Since the string is a character sequence, extend
took each of these elements and added them to la
QUESTION: was the value associated to variable s
modified?
QUESTION: The following code:
la = [60,50]
la.extend(70,90,80)
produces un error (which one?)
modifies
la
(how?)
QUESTION: If this code is executed, what happens?
sa = "hello"
sb = "world"
sa.extend(sb)
sa
is modified (how?)we get an error (which one?)
QUESTION: If this code is executed, what happens?
la = [1,2,3]
lb = [4,5]
lc = [6,7,8]
la.extend(lb).extend(lc)
la
becomes[1,2,3,4,5,6,7,8]
an error (which one?)
la
becomes[1,2,3,4,5]
and an error (which one?)
QUESTION: 3: la
becomes [1,2,3,4,5]
and right after we get an error, because the call to la.extend(lb)
MODIFIES la
to [1,2,3,4,5]
and RETURN the value None
. At that point, Python tries to call the method extend
on the object None
, but since it is not a list, we get an error (to convince yourself, verify everything with Python Tutor !!!)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-45-0a08a154ada4> in <module>
3 lc = [6,7,8]
4
----> 5 la.extend(lb).extend(lc)
AttributeError: 'NoneType' object has no attribute 'extend'
Exercise: augmenting a list 2
Given two lists la
and lb
and an element x
, write some code to MODIFY la
so that la
contains at the end the element x
followed by all other elements of lb
NOTE 1: your code should work with any
la
andlb
NOTE 2:
id
is a Python function which associates to each memory region a unique identifier. If you try printingid(la)
before modyfingla
andid(la)
afterwards, you should obtain exactly the same id. If you obtain a different one, it means you generated an entirely new list. In that case, verify how it’s working with Python Tutor.
la = [5,9,2,4]
lb = [7,1,3]
x = 8
You should obtain:
>>> print(la)
[5,9,2,4,8,7,1,3]
>>> print(lb)
[7,1,3]
>>> print(x)
8
[29]:
la = [5,9,2,4]
lb = [7,1,3]
x = 8
# write here
Exercise - zslice
Write some code which given two lists la
(of at least 3 elements) and lb
, MODIFIES lb
in such a way to add 3 elements of la
followed by the last 3 of la
.
your code must work with any list
use
extends
and slices
la = ['a','b','c','d','e','f','g','h','i','l','m','n','o']
lb = ['z']
You should obtain:
>>> print(la)
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'l', 'm', 'n', 'o']
>>> print(lb)
['z', 'a', 'b', 'c', 'm', 'n', 'o']
[30]:
la = ['a','b','c','d','e','f','g','h','i','l','m','n','o']
lb = ['z']
# write here
Exercise - Zebarerun
Write some code which given a list of three strings words
and an empty list la
, fills la
with all the first 3 characters of every string in words
.
your code must work with any list of 3 strings
use slices
Example given:
words = ["Zebras", "are", "running"]
la = []
Your code must show:
>>> print(t)
['Z', 'e', 'b', 'a', 'r', 'e', 'r', 'u', 'n']
[31]:
words = ["Zebras", "are", "running"]
la = []
# write here
insert
method
insert
MODIFIES the list by inserting an element at a specific index - all elements starting from that index will be shifted of one position to the right.
[32]:
#0 1 2 3
la = [6,7,8,9]
[33]:
la.insert(2,55) # insert the number 55 at index 2
[34]:
la
[34]:
[6, 7, 55, 8, 9]
[35]:
la.insert(0,77) # insert the number 77 at index 0
[36]:
la
[36]:
[77, 6, 7, 55, 8, 9]
We can insert after the end:
[37]:
la.insert(6,88) # insert the number 88 at index 6
[38]:
la
[38]:
[77, 6, 7, 55, 8, 9, 88]
Note that if we go beyond the end, the element is placed right after the end and no empty cells are created:
[39]:
la.insert(1000,99) # insert number 99 at index 7
[40]:
la
[40]:
[77, 6, 7, 55, 8, 9, 88, 99]
QUESTION: Given any list x
, what does this code produce? Can we rewrite it in some other way?
x.insert(len(x),66)
produces a new list (which one?)
modifies
x
(how?)an error
QUESTION: What does the following code produce?
la = [3,4,5,6]
la.insert(0,[1,2])
print(la)
prints
[1,2,3,4,5,6]
an error (which one?)
something else (what?)
QUESTION: What does the following code produce?
la = [4,5,6]
la.insert(0,1,2,3)
print(la)
prints
[1,2,3,4,5,6]
an error (which one?)
something else (what?)
QUESTION: What does the following code produce?
la = [4,5,6]
lb = la.insert(0,3)
lc = lb.insert(0,2)
ld = lc.insert(0,1)
print(ld)
prints
[1,2,3,4,5,6]
an error (which one?)
something else (what?)
Exercise - insertando
Given the list
la = [7,6,8,5,6]
write some code which MODIFIES the list by using only calls to insert
. After your code, la
should appear like this:
>>> print(la)
[7, 70, 90, 6, 8, 80, 5, 6, 50]
[41]:
la = [7,6,8,5,6]
# write here
WARNING: calling insert
is much slower than append
!!
A call to insert
rewrites all the cells after the insertion point, while append
instead adds only one cell. Given the computer is fast, very often we don’t realize the difference, but whenever possible try writing code using append
instead of insert
, especially if you have to write programs which operate on big amounts of data.
Exercise - insappend
This code takes as input an empty list la
and a list of numbers lb
. Try to understand what it does, and rewrite it using some append
.
[42]:
la = []
lb = [7,6,9,8]
la.insert(0,lb[0]*2)
la.insert(0,lb[1]*2)
la.insert(0,lb[2]*2)
la.insert(0,lb[3]*2)
print(la)
[16, 18, 12, 14]
[43]:
la = []
lb = [7,6,9,8]
# write here
pop
method
pop
method does two things: when called without arguments MODIFIES the list by removing the last element, and also RETURNS the removed element:
[44]:
basket = ['melon','strawberry', 'apple']
[45]:
basket.pop()
[45]:
'apple'
[46]:
basket
[46]:
['melon', 'strawberry']
[47]:
basket.pop()
[47]:
'strawberry'
[48]:
basket
[48]:
['melon']
Since the last element is returned by pop
, we can also assign it to a variable:
[49]:
fruit = basket.pop()
Note we don’t see no result printed because the returned element was assigned to the variable fruit
:
[50]:
fruit
[50]:
'melon'
We also notice that basket
was MODIFIED indeed:
[51]:
basket
[51]:
[]
If you further call pop
on an empty list you will get an error:
basket.pop()
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-67-086f38c9fbc0> in <module>()
----> 1 basket.pop()
IndexError: pop from empty list
Optionally, to remove an element from a specific position we can pass pop
an index from 0
INCLUDED to the length of the list EXCLUDED:
[52]:
# 0 1 2 3
tools = ['hammer', 'screwdriver', 'plier', 'hammer']
[53]:
tools.pop(2)
[53]:
'plier'
[54]:
tools
[54]:
['hammer', 'screwdriver', 'hammer']
QUESTION: Have a look at following code snippets, and for each of them try to guess the result it produces (or if it gives an error):
la = ['a'] print(la.pop()) print(la.pop())
la = [4,3,2,1] print(la.pop(4)) print(la)
la = [1,2,3,4] print(la.pop(3)) print(la)
la = [1,2,3,4] print(la.pop(-1)) print(la)
s = 'raw' print(s.pop()) print(s)
la = ['so', 'raw'] print(la.pop()) print(la)
la = ['a', ['a']] print(la.pop()) print(la)
Exercise - popcorn
Given the list corn
of exactly 4 characters, write some code which transfers in reverse order all the characters from corn
to another list box
which is initially empty.
DO NOT use methods like
reverse
or functions likereversed
Your code must work with any list
corn
of 4 elements
Example - given:
corn = ['G','u','r','u']
box = []
after your code, it must result:
>>> print(corn)
[]
>>> print(box)
['u', 'r', 'u', 'G']
[55]:
corn = ['G','u','r','u']
box = []
# write here
Exercise - zonzo
Given a list la
containing some characters, and a list lb
containing exactly two positions in ascending order, write some code which eliminates from la
the characters at positions specified in lb
.
WARNING: by calling
pop
the first time you will MODIFYla
, so the index from the second element to eliminate will need to be properly adjusted !DO NOT create new lists, so no rows beginning with
la =
Your code must work with any
la
and anylb
of two elements
Example - given:
# 0 1 2 3 4
la = ['z','o','n','z','o']
lb = [2,4]
at position 2 in la
we find the n
and at 4th the o
, so after your code it must result:
>>> print(la)
['z', 'o', 'z']
[56]:
# 0 1 2 3 4
la = ['z','o','n','z','o']
lb = [2,4]
# write here
reverse
method
reverse
method MODIFIES the list on which it is called by inverting the order of elements.
Let’s see an example:
[57]:
la = [7,6,8,4]
[58]:
la.reverse()
[59]:
la
[59]:
[4, 8, 6, 7]
WARNING: reverse
RETURNS NOTHING!
To be precise, it returns None
[60]:
lb = [7,6,8,4]
[61]:
x = lb.reverse()
[62]:
print(x)
None
[63]:
print(lb)
[4, 8, 6, 7]
QUESTION: Which effect does the following code produce?
s = "transatlantic"
s.reverse()
print(s)
an error (which one?)
prints the string in reverse
QUESTION: If x
is some list, which effect does the following produce?
x.reverse().reverse()
changes the list (how?)
it doesn’t change the list
generates an error (which one?)
Exercise - good manners
Write some code which given two lists la
and lb
MODIFY la
adding all the elements of lb
and then reversing the whole list.
you code must work with any
la
andlb
DO NOT modify
lb
Example - given:
la = ['g','o','o','d']
lb = ['m','a','n','n','e','r','s']
After your code, it must print:
>>> print('la=',la)
la= ['s', 'r', 'e', 'n', 'n', 'a', 'm', 'd', 'o', 'o', 'g']
>>> print('lb=',lb)
lb= ['m', 'a', 'n', 'n', 'e', 'r', 's']
[64]:
la = ['g','o','o','d']
lb = ['m','a','n','n','e','r','s']
# write here
Exercise - precious things
Given two lists la
and lb
write some code which PRINTS a list with the elements of la
and lb
in reverse order.
DO NOT modify
la
and DO NOT modifylb
your code must work with any list
la
andlb
Example - given:
la = ['p','r','e','c','i','o','u','s']
lb = ['t','h','i','n','g','s']
After your code, it must print:
['s', 'g', 'n', 'i', 'h', 't', 's', 'u', 'o', 'i', 'c', 'e', 'r', 'p']
[65]:
la = ['p','r','e','c','i','o','u','s']
lb = ['t','h','i','n','g','s']
# write here
Exercise - powers
The following code uses some insert
which as we already said it is not very efficient. Try to understand what it does, and rewrite it using only append
and reverse
your code must work for any value of
x
[66]:
x = 2
la = [x]
la.insert(0,la[0]*2)
la.insert(0,la[0]*2)
la.insert(0,la[0]*2)
la.insert(0,la[0]*2)
print(la)
[32, 16, 8, 4, 2]
[67]:
x = 2
la = [x]
# write here
sort
method
If a list contains homogenous elements, it is possible to sort it rapidly with the sort
method, which MODIFIES the list on which it is called (also called sorting in-place):
[68]:
la = [8,6,7,9]
[69]:
la.sort() # NOTE: sort returns nothing !!!
[70]:
la
[70]:
[6, 7, 8, 9]
Strings are also sortable
[71]:
lb = ['Boccaccio', 'Alighieri', 'Manzoni', 'Leopardi']
[72]:
lb.sort()
[73]:
lb
[73]:
['Alighieri', 'Boccaccio', 'Leopardi', 'Manzoni']
A list with non-comparable elements it’s not sortable, and Python will complain:
[74]:
lc = [3,4,'cabbage',7,'potatoes']
>>> lc.sort()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-288-0cabfae30939> in <module>
----> 1 lc.sort()
TypeError: '<' not supported between instances of 'str' and 'int'
Optionally, for reverse order you can pass the parameter reverse=True
:
[75]:
la = [4,2,5,3]
la.sort(reverse=True)
[76]:
la
[76]:
[5, 4, 3, 2]
Custom sorting
If you have custom needs like for example a lists of strings in the format 'name surname'
that you want to sort according to the surname, you should use optional parameter key
with lambda
functions, see Python docs
Exercise - numlist
Given the list la = [10, 60, 72, 118, 11, 71, 56, 89, 120, 175]
finds the
min
,max
and themedian value
(HINT: sort it and extract the right values)create a list only with elements at even indexes (i.e. [10, 72, 11, ..], note that “..” means the list is still not complete!) and ricalculates the values of min, max and median
redo the same with the elements at odd indexes (i.e. [60, 118,..])
You should obtain:
original: [10, 60, 72, 118, 11, 71, 56, 89, 120, 175]
even: [10, 72, 11, 56, 120]
odd: [60, 118, 71, 89, 175]
sorted: [10, 11, 56, 60, 71, 72, 89, 118, 120, 175]
sorted even: [10, 11, 56, 72, 120]
sorted odd: [60, 71, 89, 118, 175]
original: Min: 10 Max. 175 Median: 72
even: Min: 10 Max. 120 Median: 56
odd: Min: 60 Max. 175 Median: 89
[77]:
la = [10, 60, 72, 118, 11, 71, 56, 89, 120, 175]
# write here
join
- build strings from lists
Given a string to use as separator, and a sequence like for example a list la
which only contains strings, it’s possible to concatenate them into a (new) string with join
method:
[78]:
la = ["When", "the", "sun", "raises"]
'SEPARATOR'.join(la)
[78]:
'WhenSEPARATORtheSEPARATORsunSEPARATORraises'
As separator we can put any character, like a space:
[79]:
' '.join(la)
[79]:
'When the sun raises'
Note the original list is not modified:
[80]:
la
[80]:
['When', 'the', 'sun', 'raises']
QUESTION: What does this code produce?
''.join(['a','b','c']).upper()
an error (which one?)
a string (which one?)
a list (which one?)
QUESTION: What does this code produce?
'a'.join('KRT') + 'E'
a string (which one?)
an error (which one?)
a list (which one?)
QUESTION: What does this code produce?
'\''.join('mmmm')
an error (which one?)
a string (which one?)
QUESTION: Given any string s
and a list of strings la
of at least two characters, the following code will always give us the same result - which one? (think about it, and if you don’t know how to answer try putting random values for s
and la
)
len(s) <= len(s.join(la))
an errore (which one?)
a stringa (which one?)
something else (what?)
Exercise - barzoletta
Given the string
sa = 'barzoletta'
write some code which creates a NEW string sb
by changing the original string in such a way it results:
>>> print(sb)
'barzelletta'
USE the method
insert
and cell reassignmentNOTE: you cannot use them an a string, because it is IMMUTABLE - you will then first convert the string to a list
[81]:
sa = 'barzoletta'
# write here
Exercise - dub dab dib dob
Write some code which given a list of strings la
, associates to variable s
a string with the concatenated strings, separating them with a comma and a space.
Example - given:
la = ['dub', 'dab','dib', 'dob']
After your code, you should obtain this:
>>> print(s)
dub, dab, dib, dob
>>> len(s)
18
[82]:
la = ['dub', 'dab','dib', 'dob']
# write here
Exercise - ghirigori
Given a list of strings la
and a list with three separators seps
, write some code which prints the elements of la
separated by first separator, followed by the second separator, followed by the elements of la
separated by the third separator.
your code must work with any list
la
andseps
Example - given:
la = ['ghi','ri','go','ri']
seps = [',','_','+']
After your code, it must print:
ghi,ri,go,ri_ghi+ri+go+ri
[83]:
la = ['ghi','ri','go','ri']
seps = [',','_','+']
# write here
Exercise - welldone
Given the list:
la = ["walnut", "eggplant", "lemon", "lime", "date", "onion", "nectarine", "endive" ]:
Create another list (call it
new
) containing the first character of every element ofla
Add a space to
new
at position 4 and attach an exclamation mark ('!'
) at the endPrint the list
Print the list content by joining all elements with an empty space
You should get:
['w', 'e', 'l', 'l', ' ', 'd', 'o', 'n', 'e', '!']
well done!
[84]:
la = ["walnut", "eggplant", "lemon", "lime", "date", "onion", "nectarine", "endive" ]
# write here
copy
method
If we want to copy a mutable data structure, we can use the .copy()
method, which performs a so-called shallow copy. Let’s see what it means.
Let’s start with a simple case, for example a list of immutable objects like strings we can visualize in Python Tutor:
[85]:
satellites = ["Hubble", "Sputnik 1"]
copia = satellites.copy()
jupman.pytut()
[85]:
We clearly see how a completely new memory region was created. If we later try to modify the copy, we will see the original is not changed:
[86]:
satellites = ["Sputnik 1", "Hubble"]
my_copy = satellites.copy()
my_copy.append("James Webb")
jupman.pytut()
[86]:
copy
is shallow
So far, we didn’t notice any particular problem. But what happens if we try copy()
on a list which contains other lists, in other words, other mutable elements, and then try mutating one of the two?
[87]:
biglistA = [ ['Pay', 'attention'],
['to', 'where'],
['the', 'arrows', 'point to']
]
biglistB = biglistA.copy()
biglistA[2][0] = 'CAREFUL!' # we write into the original...
print(biglistA)
print(biglistB)
jupman.pytut()
[['Pay', 'attention'], ['to', 'where'], ['CAREFUL!', 'arrows', 'point to']]
[['Pay', 'attention'], ['to', 'where'], ['CAREFUL!', 'arrows', 'point to']]
[87]:
Note we have two big lists containing cells that point to shared sublists: as a matter of fact, by writing into a subcell of biglistA we also write into biglistB!
In other words, .copy()
performs only a shallow copy, for a proper deep copy we will need to find some other way!
deepcopy
function
To avoid sharing problems we can use the so-called deep copy, available in the function deepcopy
from module copy
WARNING: deepcopy
IS NOT a list method!
Let’s try again the example with copy.deepcopy
: we will now get completely distinct data structures:
[88]:
# first we import `copy`, which is a PYTHON MODULE
import copy
biglistA = [ ['Pay', 'attention'],
['to', 'where'],
['the', 'arrows', 'point to']
]
# then we call its function deepcopy, passing the parameter biglistA:
biglistB = copy.deepcopy(biglistA)
biglistA[2][0] = 'CAREFUL!' # we write into the original...
print(biglistA)
print(biglistB)
jupman.pytut()
[['Pay', 'attention'], ['to', 'where'], ['CAREFUL!', 'arrows', 'point to']]
[['Pay', 'attention'], ['to', 'where'], ['the', 'arrows', 'point to']]
[88]:
Continue
You can find more exercises in the worksheet Lists 4 - Search methods