In [2]:
from notebook.services.config import ConfigManager
from IPython.paths import locate_profile
cm = ConfigManager(profile_dir=locate_profile(get_ipython().profile))
cm.update('livereveal', {
              'theme': 'league',
              'transition': 'zoom',
              'start_slideshow_at': 'selected',
})


Out[2]:
{'start_slideshow_at': 'selected', 'theme': 'league', 'transition': 'zoom'}

Lists and Loops

Dr. Chris Gwilliams

gwilliamsc@cardiff.ac.uk

Overview So Far

  • Introduction to Python
  • Types
  • Variables
  • Functions (built in and your own)
  • Methods
  • Scope
  • Imports

This Session

  • Lists
    • indexing
    • negative indexing
    • Operations and length
  • Loops
  • Iteration
  • Recursion
  • Understanding the difference

Input

First thing to note: If you want the user to be able to input their own information, you can use the input function to store their result.

name = input("Please add your name: ")
print(name)

Exercise

Create a variable that holds a value. Ask the user for input. If the input is > 20, multiple the two and print the result. Otherwise, divide the two and print it.

Storing Multiple Values

Exercise

Write a script that stores the names of 5 of your peers.

name_one = "Sarah"
name_two = "Rick"
name_three = "Morty"
  • Now how would you do that for 100?

Lists

Lists (also known as arrays) are data structures that can hold a collection of literals (often called elements).

my_list = ['1', 2, True] my_list = []

Can be instantiated with values or declared empty.

Zero-indexed and accessed with square brackets ([])

mylist[0] #'1'

Exercise

Lists are mutable, but strings are immutable.

What does that mean?

list_one = ['cat', 'dog', 'hamster']
list_two = list_one
list_two.append('narwhal')
print(list_one)

What will the code above output?

Lists are mutable, which means you can change their content without changing how they are identified.

Immutable types, like strings, cannot be changed without the identity of the variable also changing.

The code would print ['cat', 'dog', 'hamster', 'narwhal'], despite it being a different variable, all the references point to the same place!

Accessing Elements in a List

Square bracket notation

We use square brackets and the number of the index (or key) in the list in order to access the value.


In [36]:
movie_list = ['The Godfather', 'Jaws', 'Troy', 'Midnight Special', 'Casper']

Exercise

What index is the Godfather?

Print the 4th element

Make the second element equal Toy Story

Print the length of the list


In [37]:
# 0
print(movie_list[3])
movie_list[1] = "Toy Story"
print(len(movie_list))


Midnight Special
5

Accessing Elements in a List

How would we print the last element of the list in the previous example?

print(movie_list[4])

What if we do not know the size of the list?


In [38]:
# Python knows the size

print(movie_list[len(movie_list)])


---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-38-61bafca28bdf> in <module>()
      1 # Python knows the size
      2 
----> 3 print(movie_list[len(movie_list)])

IndexError: list index out of range

In [39]:
print(len(movie_list))

# Why will this not work?


5

Lists in Python are zero-indexed. But if the len function told us there were 4 elements (including 0), that would be confusing!

So, the length of a list may be 5 elements but we have to access them using zero-indexed indices. So, how would we get the last element?


In [40]:
print(movie_list[len(movie_list) - 1])


Casper

Accessing Elements in a List

Reverse Indexing

Using the method from the previous slides is pretty longwinded, although useful. This is the way to do it in most programming languages.

However, Python is not always like most programming languages. In this case, we have reverse indexing! Which works just how it sounds.


In [42]:
print(movie_list[-1]) #last element
print(movie_list[-2]) #second to last


Casper
Midnight Special

The best way to think of negative indexing is to see:

list[-X]

as

list[len(list)-X]

Exercise

  • Instantiate a list with 3 elements inside
  • Print the first element
  • Change the first element to equal house
  • Print the whole list
  • Print the length of the list
  • Print the second to last element
  • Create an empty list
  • What happens when you try and print the second element?
  • What about when you assign a literal to the first element?

In [1]:
three_elements = [1, 2, 3]
print(three_elements[0])
three_elements[0] = 'house'
print(three_elements)
empty_list = []
print(empty_list[1]) #IndexError
empty_list[0] = 1 #IndexError


1
['house', 2, 3]
----------------------------------------------------------------------
IndexError                           Traceback (most recent call last)
<ipython-input-1-5c35cd54106f> in <module>()
      4 print(three_elements)
      5 empty_list = []
----> 6 print(empty_list[1])
      7 empty_list[0] = 1

IndexError: list index out of range

Adding to Lists

Lists, like all Python objects, have methods built into them. We can find these out by using the dir function


In [2]:
dir([])


Out[2]:
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__delitem__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__gt__',
 '__hash__',
 '__iadd__',
 '__imul__',
 '__init__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__reversed__',
 '__rmul__',
 '__setattr__',
 '__setitem__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'append',
 'clear',
 'copy',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']

Adding to Lists


In [4]:
awful_movies = []
awful_movies.append('The Artist')
awful_movies.append('The Room')
awful_movies.append('Rambo 4')
print(awful_movies)


['The Artist', 'The Room', 'Rambo 4']

Exercise

Create the list above. Using the dir and help functions, do the following:

  • Copy the list to a new list and call it great_movies
  • Pop the last element off the new list
  • What is the method to count the number of occurrences of an item in a list?
  • Print the number of occurrences of Rambo 4

In [17]:
great_movies = awful_movies.copy()
print(my_film.pop())
print(awful_movies)
#count('item_to_find')
print(awful_movies.index('Rambo 4'))


Rambo 4
['The Artist', 'The Room', 'Rambo 4']
2

LIFO and FIFO

Lists in Python are just that: lists of elements. But how we add and remove items is dependent on the type of data structure.

Last In First Out

Think of a shopping cart that you fill as you go around a supermarket. Assuming you are organised and fill from the bottom up, then you will empty the cart at the checkout with the last items you put in there first.

First In First Out

Now think of the conveyor belt that you put the shopping on. When the checkout assistant (or robot that will soon replace them) gets to scan the items.

Exercise

Which of the examples are FIFO and which are LIFO?

  • Backpack
  • Supermark Queue
  • Smarties packet
  • Baggage carousel
  • LIFO
  • FIFO
  • LIFO
  • FIFO

Iteration

Repeating a set of instructions n times or until a specified result has been achieved.

What are some examples of iteration?

  • for loops
  • while loops

For loops

Looping through a specified number of times, such as the length of a list.


In [4]:
my_list = [1, 2, 3, 4, 5]
print("Length of list is: {0}".format(len(my_list)))
#for i  in range(len(my_list)):
#    print(i)
#    print(my_list[i])
    
for jimmy in range(5):
    print(jimmy)


Length of list is: 5
0
1
2
3
4

Exercise

Modify the above code to print out the value at the index of the list

Iterating Over Lists

There are multiple ways we can iterate over a list and access the elements within:


In [12]:
my_list = ['cats', 'hippopotamus', 'weasel', 'glorbanflorb']
for index in range(len(my_list)):
    print(index) # just the index
print('---------')
for key, value in enumerate(my_list):
    print(key, value) #access both key and value
print('---------')
for value in my_list: #Called a For in or a For each loop
    print(value) #access just value but NO index
    
# Is one better than the others?


0
1
2
3
---------
0 cats
1 hippopotamus
2 weasel
3 glorbanflorb
---------
cats
hippopotamus
weasel
glorbanflorb

Iterating Over Lists

As expected, there is no silver bullet, each of these solutions is perfectly viable. However, when needing both index and value, enumerate is recommended because it supports multiple data types.

There are many studies that show the memory usage and execution time of range and enumerate, but that is beyond the scope of this course.

Exercise

  • Create a list of some cities in the UK (use people at your table)
  • Loop through them and print them out
  • Print the index of the city if it contains the letter h

In [16]:
cities = ['Manchester', 'Cardiff', 'London', 'Southampton']
for key,value in enumerate(cities):
    print(value)
    if 'h' in value:
        print("H found at index: {0}".format(key))


Manchester
H found at index: 0
Birmingham
H found at index: 1
London
Southampton
H found at index: 3

Exercise

Given the list [31,45,12,300,40000,2]

Write a for loop to calculate the sum of all the values and print out the mean of all values


In [17]:
nums = [31,45,12,300,40000,2]
total = 0
for num in nums:
    total += num
print("Total is {0}".format(total))
print("Mean is {0}".format(total/len(nums)))


Total is 40390
Mean is 6731.666666666667

Controlling Iteration

Sometimes, we may only want to execute when certain elements match some criteria we define. Like in the example above, we can use if statements for this, but there are some other keywords

break

Using the break keyword, we can break out of our loop before it has finished. Why might this be useful?


In [5]:
bad_words = ['fudge', 'bar steward', 'doody head']
my_string = input()
my_string_list = my_string.split(' ') #split at space to create a list of words
for word in my_string_list:
    if word in bad_words:
        print("Whoa now, no need for obscenities")
        break
    else:
        print(word)


I like fudge pieces
  File "<string>", line 1
    I like fudge pieces
         ^
SyntaxError: invalid syntax

Exercise

Write a for loop that asks a user for 5 positive integers and adds them to a list

Break out of the loop if the user input is not an integer

Print the mean if all 5 are input

Hint:

  • Write the code to add to the list first
  • You can check if a string is a positive integer using isdigit

What other ways could we use to check if the input variable is a number?


In [28]:
user_nums = []
total = 0
for i in range(0, 5):
    user_input = input("Enter a positive integer please: ")
    if user_input.isdigit():
        user_nums.append(user_input)
        total += int(user_input)
    else:
        print("I said POSITIVE NUMBER!")
        break
if len(user_nums) == 5:
    print(total/len(user_nums))


Enter a positive integer please: 1
Enter a positive integer please: 2
Enter a positive integer please: 5
Enter a positive integer please: 6
Enter a positive integer please: 7
4.2

continue

The continue keyword passes over the current iteration and heads straight for the next one. For example, if a value matches a value we do not want.

The difference here is that the loop does not stop. The loop continues until the end and just skips when continue is used.


In [29]:
for i in range(0, 5):
    if i == 2:
        continue #head back to the top and go to the next value for i
    print(i) #if i == 2 then this line is not executed


0
1
3
4

Exercise

Write a for loop that only prints out only the consonants of a word input by the user.

Hint: looping through a string using a for...in loop gives you each letter


In [30]:
user_string = input()
vowels = ['a', 'e', 'i', 'o', 'u']
for letter in user_string:
    if letter in vowels:
        continue
    print(letter)


sausage
s
s
g

pass

pass is a keyword used when we do not want to execute a block of code. Typically, you would not use this in a loop but it can have benefits when you are developing.

For example: what happens if you create a function but do not write any code for it yet?


In [31]:
def my_function():


  File "<ipython-input-31-ff58bf0093ce>", line 2
    
    ^
SyntaxError: unexpected EOF while parsing

In [32]:
def my_function():
    pass

List Comprehension

Lists in Python are more powerful than general arrays in most other languages. Lists allow you to perform comprehensions, which are really just instructions that generally cover multiple lines, condensed down into a single line. For example, consider creating a list of all odd numbers between 1 and 100.

How might we do this?


In [3]:
odd_list = []
# for i in range(1, 100, 2):
#    odd_list.append(i)
    
for i in range(1, 100):
    if i % 2 != 0:
        odd_list.append(i)
        
print(odd_list)


[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]

In [7]:
odd_list = [x for x in range(1, 100, 2)] # list comprehension is comprehensive!
print(odd_list)


[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]

While Loops

While loops are another form of iteration, calling a block of code while a condition is true.

All of the above keywords can be used within while loops and other Python code.


In [33]:
i = 0
while(i < 6):
    print(i)
    i += 1


0
1
2
3
4
5
6
7
8
9

Infinite Loops

Be careful with while loops as they do not change the value like a for loop does!


In [ ]:
i = 0
while(i < 10):
    print(i) #how many times will i be printed?

HINT: CTRL-C ends a script

Sometimes, infinite loops can be useful. For example, we may want to keep receiving information from a client if we are listening for new files or input from a user if we are making a text-based game

Exercise

Write a while loop that prints what a user has typed. If the user types quit then exit the loop If the user enters dnp then do not print but still prompt them to enter more text


In [ ]:
while(True):
    user_string = input("Tell me a secret: ")
    if user_string == "quit":
        break
    elif "dnp" in user_string:    
        continue
    else:
        print(user_string)

Homework

  1. How is a list different from an array in other languages? (max. 200 words)
  2. Create an empty list
  3. Use a while loop to add numbers to the list until the user enters quit
  4. Print out the first and last elements of the list
  5. Loop through the list and print out the index of each even number
  6. Print out the mean