Lists and loops¶
A list is the first type of data structure that we meet in this course. While "data structure" may sound complicated, is just a collection of data elements (e.g. numbers or strings) that is structured in some way (e.g. by numbering the elements). The list is a sequence, where each element has an index, i.e. its position in the list.
You can create a new list using the square brackets [], or the list() function:
list1 = ["first", "second", "third"]
list2 = list((1,2,3))
list3 = ['cake', 4, 7.9, "apple"]
Properties of lists to remember:
- Values don't have to be of the same type (see
list3) - You can modify lists after you create them (they are mutable)
- Elements can be changed, added and deleted
- Lists are versatile and are used extensively in typical Python code
Accessing elements in a list¶
Just like you did this morning - accessing elements of strings - elements in a list are accessed by their index.
Remember:
- index by square brackets
[] - note how index starts at zero!
list1[1]
'second'
list1[0]
'first'
negative indexes go back from the end:
list1[-1]
'third'
Trying to access an element in a list that is out of range throws an IndexError; good to know how long the list is ...
list1[4]
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-7-b02c477e8a73> in <module>() ----> 1 list1[4] IndexError: list index out of range
len(list1)
3
Modify your list!¶
Remember that lists are mutable? This means that we can change, add and remove items from a list!
1. Changing Items¶
list2
[1, 2, 3]
list2[0] = 4
list2
[4, 2, 3]
Assigning to a position past the end of the list also throws an IndexError
list2[5] = 9
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-12-c1b1fb30f16a> in <module>() ----> 1 list2[5] = 9 IndexError: list assignment index out of range
2. Appending and Extending¶
list1.append("fourth")
list1
['first', 'second', 'third', 'fourth']
If you want to append more than one item, you can use the extend function:
list1.extend()
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-15-4f4f0d499a0f> in <module>() ----> 1 list1.extend() TypeError: extend() takes exactly one argument (0 given)
3. Removing and Inserting Items¶
Items at arbitrary positions can be removed using the del statement:
list1
['first', 'second', 'third', 'fourth']
del(list1[2])
list1
['first', 'second', 'fourth']
Alternatively, you can use the pop function:
list1.pop()
'fourth'
list1.pop(1)
'second'
insert function: insert(index, item)
list1.insert(2, "three")
list1
['first', 'three']
note: appending items to the end of the list using append is more efficient than inserting at the end
4. Adding lists = concatenating lists¶
list4 = list1 + list2 + list3
list4
['first', 'three', 4, 2, 3, 'cake', 4, 7.9, 'apple']
5. Multiplying lists¶
Multiplying a list by a number does not multiply the elements of the list, but the whole list:
(NB: this is specific to sequences. Other data structures have element-wise multiplication as you will see later in the course)
list5 = list4 * 5
list5
['first', 'three', 4, 2, 3, 'cake', 4, 7.9, 'apple', 'first', 'three', 4, 2, 3, 'cake', 4, 7.9, 'apple', 'first', 'three', 4, 2, 3, 'cake', 4, 7.9, 'apple', 'first', 'three', 4, 2, 3, 'cake', 4, 7.9, 'apple', 'first', 'three', 4, 2, 3, 'cake', 4, 7.9, 'apple']
List slicing¶
A copy of a sublist can be created using the slice operator list[start:end]
The element at the index start is included, the one at end is excluded (remember slicing strings with Fabian this morning?)
Both indices can be ommitted, defaulting to the start and end of the list respectively
list4[0:5]
len(list4[0:5])
list4[0:5]
['first', 'three', 4, 2, 3]
list4[4:]
[3, 'cake', 4, 7.9, 'apple']
list4[:6]
['first', 'three', 4, 2, 3, 'cake']
list4[:]
['first', 'three', 4, 2, 3, 'cake', 4, 7.9, 'apple']
to slice in bigger steps, include a stepsize:
list4[0::2]
['first', 4, 3, 4, 'apple']
Variables and References¶
NB: in Python, all variables are references
The = operator does not copy an object, it just creates another reference (name) for the same object!
list5 = list4
list5
['first', 'three', 4, 2, 3, 'cake', 4, 7.9, 'apple']
list5.pop()
'apple'
list5 = list4
Check: they both point to the same memory address; i.e. both list1 and list5 refer to the same list.
print(id(list5))
print(id(list4))
892707494536 892707494536
-> if you want to create a new list with the same contents as another list, you need to copy it
range()¶
- One very commonly needed list is the list of consecutive integers (e.g. for looping – more about that in a bit)
- The built-in
range([start], end)function creates such lists
myrange = list(range(10))
myrange
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
range(3,15)
range(3, 15)
list(range(3,15))
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
For Loops¶
When programming, you often want to do the same task for each point in a data set. Some examples:
- You have the attendance list of the Python course and for each participant, you want to print their department
- You have two lists, for each item in list A check whether it is also in list B
- You want to call a function for each element of an array
Notice how the structure of the programming command follows a natural logic: FOR each item: DO some action
tutors = ['Fabian', 'Lea', 'Dimitris', 'Joe', 'Ingolf']
for index, name in enumerate(tutors):
print (index)
print (name)
0 Fabian 1 Lea 2 Dimitris 3 Joe 4 Ingolf
for name in tutors:
print(len(name))
6 3 8 3 6
Different ways of iterating¶
1. range()¶
range() returns a list of plain integers.
Thus, one way to loop over a sequence is to use range() on the length of a sequence -> the returned list are the indexes of the sequence. You can then access each element by index:
range(5)
range(0, 5)
for i in range(len(tutors)):
print(tutors[i])
Fabian Lea Dimitris Joe Ingolf
2. enumerate()¶
enumerate() returns a tuple containing a count and the values obtained from iterating over sequence. This is handy if you need both the item a sequence and its index.
for index,name in enumerate(tutors):
print(index, name)
0 Fabian 1 Lea 2 Dimitris 3 Joe 4 Ingolf
We have seen how for loops allow us to easily execute the same statement for each item in a list. But what if we want to apply different statements, depending on the item?
In our earlier example, say you want to print the name, but only if it contains the letter i. So now when you initialize the iterator, there are actually 2 different options and we need to check which one is the case:
if the name contains the letter i -> print the name --> whiteboard
These check-points are called conditionals; you check whether a condition is met. And the whole concept is referred to as flow control, because at these check points, you control "in which direction the programme is going to flow".
Flow control¶
1. conditionals - keywords¶
if¶
use the if keyword to check whether a condition is met:
for number in range(8):
if number % 2 == 0:
print(number, ' is even')
0 is even 2 is even 4 is even 6 is even
use the else keyword to specify a statement that is executed when the condition is not true:
else¶
for number in range(8):
if number % 2 == 0:
print(number, 'is even')
else:
print(number, 'is odd')
0 is even 1 is odd 2 is even 3 is odd 4 is even 5 is odd 6 is even 7 is odd
use the elif keyword to check for several conditions:
elif¶
for number in range(8):
if number % 2 ==0:
print(number, 'is even')
elif number == 3:
print(number, 'is my favourite number!')
else:
print(number, 'is odd')
0 is even 1 is odd 2 is even 3 is my favourite number! 4 is even 5 is odd 6 is even 7 is odd
2. conditionals - expressions¶
question: which expressions can you use as condition for an if statement?
- anything that evaluates to a boolean value
- Boolean values are
TrueandFalse
e.g. comparison of numeric types¶
Numeric types can be compared using the comparison operators, which yield True or False The operators are:
a < b | a less than b
a > b | a greater than b
a == b | a equal to b
a <= b | a less than or equal to b
a >= b | a greater than or equal to b
The boolean values True and False can be combined using the boolean operators and, or, and not
a = True
b = False
a and b
False
a and 3 <= 4
True
e.g. testing for membership¶
here the keyword is in
mondaytutors = ["Fabian", "Lea", "Dimitris, Ingolf"]
alltutors = ["Fabian", "Joe", "Ingolf", "Lea", "Alison", "Matthias", "Michael", "Thanapong", "Peter",
"Dimitris", "Sheen", "Chris", "Auro", "Gaurav", "Ope"]
for tutor in alltutors:
if tutor in mondaytutors:
print(tutor)
Fabian Lea
Using for loops on lists and list comprehensions¶
You commonly want to create a new list by transforming and filtering an old list:
even_numbers = []
for x in range(10):
if x % 2 == 0:
even_numbers.append(x)
even_numbers
[0, 2, 4, 6, 8]
Because this is such a common operation Python also provides a shortcut in form of list comprehensions (they are truely great!)
even_numbers = [x for x in range(10) if x % 2 == 0]
even_numbers
[0, 2, 4, 6, 8]
References and further reading¶