This notebook mirrors the Google Python Course: Lists.
See Lists from Socratica.
Lists in python are sequences of objects, delimited by square brackets and separated by commas. Just as strings in python are sequences of characters. Strings have a length and can be indexed and sliced. Lists share these properties.
l = [1,2,3,4,5]
l
[1, 2, 3, 4, 5]
len(l)
5
l[0]
1
l[4]
5
l[-1]
5
l[1:4]
[2, 3, 4]
l[::-1]
[5, 4, 3, 2, 1]
l[6]
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) /tmp/ipykernel_66087/3206022998.py in <module> ----> 1 l[6] IndexError: list index out of range
As you can see, lists pretty much behave as expected compared to strings.
We will often want to iterate over a list. That is, we will execute some code for each element of the list. One common way to do this in python is using a for
loop.
for element in l:
print (element*2, end='')
print (' x')
print ('y')
2 x 4 x 6 x 8 x 10 x y
In this example, the local variable element
is bound to each successive element in the list l. We print out that element times 2. Note that for loop uses a colon (:) to specify the start of the code block to be executed for each element
Below we add up the numbers in a list.
sum = 0
for element in l:
sum = sum + element
sum
15
We can write the addition and assignment more succinctly.
sum = 0
for element in l:
sum += element
sum
15
Alas, python does not have the wonderful autoincrement operator ++
, found in C, Java, JavaScript, and, of course, C++.
The for loops above used in. We may also use in as a boolean (true/false) to test membership in a list.
3 in l
True
6 in l
False
'hello' in l
False
'h' in 'hello'
True
6 not in l
True
When we iterate through a list, we sometimes want both the sequential values and the indices of the respective values. enumerate
solves this problem.
enumerate(l)
<enumerate at 0x7f5e54178a80>
list(enumerate(l))
[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]
enumerate returns an object which generates a list of tuples (index, element) We will look at tuples later on.
for i, element in enumerate(l):
print (i, element)
0 1 1 2 2 3 3 4 4 5
for i, element in enumerate(l):
l[i] = element*element
l
[1, 4, 9, 16, 25]
l now contains the squares of each former element in l. Let's try it again.
for i, element in enumerate(l):
l[i] = element*element
l
[1, 16, 81, 256, 625]
We often want list of sequential integers - usually the first n integers. range()
does the job.
Note that range returns a range object which is a generator, not a list. We can convert the generator to a list using the list()
construction for the list class.
r = range(10)
r
range(0, 10)
type(r)
range
list(r)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Thus, range(10) produces the first 10 integers, starting with 0. We can provide a different start value than 0.
list(range(5,10))
[5, 6, 7, 8, 9]
list(range(10,20))
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
As with slices, we can also provide a different step value. If the step value is negative, the start must be bigger than the end.
list(range(10,20,2))
[10, 12, 14, 16, 18]
list(range(20,10,-2))
[20, 18, 16, 14, 12]
list(range(10,-10,-1))
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
list(range(20,10))
[]
In addition to the for loop, python has a while loop for iteration. The body of the loop is executed as long as the condition is true.
i = 0
l = range(10)
while i < len(l):
print (l[i])
i += 3
0 3 6 9
list.append(element)
- Adds a new element to the end of the list. Common error: does not return a copy, but modifies original list.
list.extend(list2)
- Adds the elements of list2 to the end of list. Using += on a list is similar.
list.insert(index, element)
- Inserts the element at the given index, shifting elements to the right.
l = list(range(5))
l
[0, 1, 2, 3, 4]
l.append(6)
l.append(8)
l
[0, 1, 2, 3, 4, 6, 8]
l.extend(range(4))
l
[0, 1, 2, 3, 4, 6, 8, 0, 1, 2, 3]
l.extend(l) ## clone the list to itself
l
[0, 1, 2, 3, 4, 6, 8, 0, 1, 2, 3, 0, 1, 2, 3, 4, 6, 8, 0, 1, 2, 3]
l.insert(0,100)
l
[100, 0, 1, 2, 3, 4, 6, 8, 0, 1, 2, 3, 0, 1, 2, 3, 4, 6, 8, 0, 1, 2, 3]
list.index(element)
- return the index of the first occurence of element in the given list. If the element is not present, throws an error. You should test for membership with in first to avoid this error.
list.remove(element)
- removes the first occurence of the given element from the list. Throws a ValueError if not present.
list.sort()
- sorts the elements of the list in place. Does not return a copy. (The sorted() function below if preferred.)
list.reverse()
- reverses the order of the list. Does not return a copy.
l = list(range(5))
l
[0, 1, 2, 3, 4]
l.index(3)
3
l.index(9)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) /tmp/ipykernel_66087/303500380.py in <module> ----> 1 l.index(9) ValueError: 9 is not in list
1 in l
True
9 in l
False
3 is l[3]. 9 is not an element of l.
l.remove(3)
l
[0, 1, 2, 4]
l.remove(9)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) /tmp/ipykernel_66087/3447356405.py in <module> ----> 1 l.remove(9) ValueError: list.remove(x): x not in list
l2 = [1,2,3,4,1,2,3,4,1,2,3,4]
l2
[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
l2.remove(3)
l2
[1, 2, 4, 1, 2, 3, 4, 1, 2, 3, 4]
l2.remove(3) removed just the first occurence of 3 in the list. The other two remain.
l
[0, 1, 2, 4]
l.sort()
l
[0, 1, 2, 4]
l2
[1, 2, 4, 1, 2, 3, 4, 1, 2, 3, 4]
l2.sort()
l2
[1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4]
l was already sorted. When we sort l2, the list is changed.
sort has an optional parameter reverse which defaults to False. If you set it to True, you get the sort in descending order.
l.sort(reverse=True)
l
[4, 2, 1, 0]
l2.sort(reverse=True)
l2
[4, 4, 4, 3, 3, 2, 2, 2, 1, 1, 1]
If you want to reverse the order of a list without sorting, you can use the reverse() method.
l3 = [1,2,3,4,1,2,3,4]
l3
[1, 2, 3, 4, 1, 2, 3, 4]
l3.reverse()
l3
[4, 3, 2, 1, 4, 3, 2, 1]
l3[::-1]
[1, 2, 3, 4, 1, 2, 3, 4]
l3
[4, 3, 2, 1, 4, 3, 2, 1]
list.pop()
- removes and returns the tail element of the list. It is the opposite of append. If you pop an empty list, [], Python throws an error.
A common data structure is a stack which implements a Last In First Out (LIFO) process. You append (or push) items onto a stack and remove them with pop. We will implement stacks later on and also see that the Python interpreter (Python Virtual Machine) is itself implemented using a stack. There is world of pops in your future.
l3
[4, 3, 2, 1, 4, 3, 2, 1]
l3.pop()
1
l3.pop()
2
l3
[4, 3, 2, 1, 4, 3]
l4 = [1]
len(l4)
1
l4.pop()
1
len(l4)
0
l4.pop()
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) /tmp/ipykernel_66087/2418603820.py in <module> ----> 1 l4.pop() IndexError: pop from empty list
You can assign new values to elements of lists.
l5 = [1,2,3,4]
l5
[1, 2, 3, 4]
l5[0] = 7
l5[3] = 12
l5
[7, 2, 3, 12]
l5[6] = 0
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) /tmp/ipykernel_66087/3960519829.py in <module> ----> 1 l5[6] = 0 IndexError: list assignment index out of range
End of lists notebook.