CSc 250: Lecture Notes: lists and for loops

In this section we are going to discuss the list data type along with for loops, which are two topics that go hand-in-hand. The official python tutorial has a brief introduction to lists, which may serve as a helpful reference for this section.

Lists

The description of lists from the official python 3 tutorial goes as follows:

Python knows a number of compound data types, used to group together other values. The most versatile is the list, which can be written as a list of comma-separated values (items) between square brackets. Lists might contain items of different types, but usually the items all have the same type.

The list type is actually pretty self-documenting. A list is a sequence of values of a particular type. Lists are declared by putting a comma-separated list of values in between square-brackets. For example, the following declares a new list of 5 integers:

>>> numbers = [5, 10, 20, 50, 100]

Similarly, we can declare lists of other types (for example, strings and floats)

>>> names = ['Billy', 'Jane', 'Rachel', 'Robert']
>>> more_numbers = [3.14, 1.11, 77.77778]

Lists an even have multiple different types in the same list (though, this is not recommended as “good programming style”):

stuff = [5, 77.7, 'Sherlock']

All of these new variables have the type list:

>>> type(numbers)
<class 'list'>
>>> type(names)
<class 'list'>
>>> type(more_numbers)
<class 'list'>
>>> type(stuff)
<class 'list'>

Regardless of what type(s) the list contains, the type of the list itself is the same.

Lists are not much use to use if we cannot access the elements within the list. Do do so, use the list indexing syntax, which also uses square brackets. List indexing is “zero-based.” This means that the first element in the list is at index 0, the second at index 1, the third at index 2, and so on.

To get the first element in the numbers list:

>>> numbers[0]
5

To get the last element:

>>> numbers[4]
100

As with strings, we can also get a range of elements from a list, using the same range syntax. To get the first, second, and third element, do:

>>> numbers[0:3]
[5, 10, 20]

To get all elements except for the first one, do:

>>> numbers[1:]
[10, 20, 50, 100]

To get just the first element:

>>> numbers[:1]
[5]

And so on.

List length

There is a built-in function in python named len. This function can be used to compute the length of lists and strings. To compute the length of all of the lists from the last example:

>>> len(numbers)
5
>>> len(names)
4
>>> len(more_numbers)
3
>>> len(stuff)
3

Getting the length of the function is useful for many reasons. One particular use case it in selecting portions of a list dynamically.

Say we have this list of numbers:

>>> square_numbers = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121]

To get the last element in this list, we could do:

>>> square_numbers[11]
121

Because we know the list has 12 elements in it. But perhaps we want to get the last element of this list without hard-coding the length. How can we do this. In this case, len comes in handy.

>>> last = len(square_numbers) - 1
>>> square_numbers[last]
121

Notice that one must be subtracted from the result of len because indexing lists is zero-based.

We can extend this example to get other sections of the list. For example, to get the second-half of the list:

>>> last = len(square_numbers) - 1
>>> middle = int(last / 2)
>>> square_numbers[middle+1:]
[36, 49, 64, 81, 100, 121]

And to get the first half:

>>> square_numbers[0:middle+1]
[0, 1, 4, 9, 16, 25]

“in” List

It is often useful to quickly check if a particular value exists inside of a list. In python you can use the in keyword to do this.

>>> movies = ['Batman', 'StarWars', 'StarTrek', 'JohnWick']
>>> 'StarTrek' in movies
True
>>> 'JohnWick' in movies
True
>>> 'JohnWick Chapter 2' in movies
False
>>>

Note that the in keywords also works for strings:

>>> title = 'John Wick Chapter 2'
>>> 'John' in title
True
>>> 'Johnny' in title
False
>>>

Generating Lists

It is sometimes useful to quickly generate a list of numbers (especially when used with for loops, which we will get to shortly). To do this, we create a new range of numbers and then convert it to a list with casting. To generate a list of numbers 1-10, run:

>>> list(range(1,11))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

50-100:

>>> list(range(50,101))
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]

You can specify an optional third argument to range, which is a “step” count. The generated list will skip this many numbers in-between each element of the list. The following generates a sequence from 50 to 100, but only includes every-other number:

>>> list(range(50,101,2))
[50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100]

In this example, we get all the multiples of ten between 0 and 100:

>>> list(range(0,101,10))
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

Modifying lists

As with strings, there are several functions that can be used to search/modify/probe the elements in a list. Below is basic documentation on many (but not all) of the commonly-used list functions.

list.append

This function will add a single element to the end of a list.

>>> names = ['Lebron', 'Kyrie', 'Steph']
>>> print(names)
['Lebron', 'Kyrie', 'Steph']
>>> names.append('Russ')
>>> print(names)
['Lebron', 'Kyrie', 'Steph', 'Russ']
>>> names.append('Devin')
>>> print(names)
['Lebron', 'Kyrie', 'Steph', 'Russ', 'Devin']

list.extend

This function will add the elements from one list to the end of another list.

>>> names = ['Lebron', 'Kyrie', 'Steph']
>>> print(names)
['Lebron', 'Kyrie', 'Steph']
>>> names.extend( ['Russ', 'Devin', 'Klay'] )
>>> print(names)
['Lebron', 'Kyrie', 'Steph', 'Russ', 'Devin', 'Klay']

list.insert

Insert an elements into the list at a particular index, and shift the rest of the list to make room for it. This function takes two arguments. The first is the index to insert at, and the second is the element to insert.

>>> names = ['Lebron', 'Kyrie', 'Steph']
>>> names.insert(1, 'Kevin')
>>> print(names)
['Lebron', 'Kevin', 'Kyrie', 'Steph']
>>> names.insert(0, 'Russ')
>>> print(names)
['Russ', 'Lebron', 'Kevin', 'Kyrie', 'Steph']
>>> names.insert(3, 'Steph')
>>> print(names)
['Russ', 'Lebron', 'Kevin', 'Steph', 'Kyrie', 'Steph']

list.remove

This function removes the first element in the list with the given value:

>>> names = ['Russ', 'Lebron', 'Steph', 'Kevin', 'Steph', 'Kyrie', 'Steph', 'Steph']
>>> names.remove('Steph')
>>> print(names)
['Russ', 'Lebron', 'Kevin', 'Steph', 'Kyrie', 'Steph', 'Steph']
>>> names.remove('Steph')
>>> print(names)
['Russ', 'Lebron', 'Kevin', 'Kyrie', 'Steph', 'Steph']
>>> names.remove('Kyrie')
>>> print(names)
['Russ', 'Lebron', 'Kevin', 'Steph', 'Steph']

list.pop

Removes and returns the element from the list at the given index.

>>> names = ['Russ', 'Lebron', 'Kevin', 'Kyrie', 'Steph', 'Klay', 'Eric']
>>> names.pop(1)
'Lebron'
>>> print(names)
['Russ', 'Kevin', 'Kyrie', 'Steph', 'Klay', 'Eric']
>>> names.pop(3)
'Steph'
>>> print(names)
['Russ', 'Kevin', 'Kyrie', 'Klay', 'Eric']
>>> names.pop(0)
'Russ'
>>> print(names)
['Kevin', 'Kyrie', 'Klay', 'Eric']

list.sort

Sorts the list.

>>> names = ['Russ', 'Lebron', 'Kevin', 'Kyrie', 'Steph', 'Klay', 'Eric']
>>> names.sort()
>>> print(names)
['Eric', 'Kevin', 'Klay', 'Kyrie', 'Lebron', 'Russ', 'Steph']

list.reverse

Reverses the elements in the list

>>> names = ['Russ', 'Lebron', 'Kevin', 'Kyrie', 'Steph', 'Klay', 'Eric']
>>> print(names)
['Russ', 'Lebron', 'Kevin', 'Kyrie', 'Steph', 'Klay', 'Eric']
>>> names.reverse()
>>> print(names)
['Eric', 'Klay', 'Steph', 'Kyrie', 'Kevin', 'Lebron', 'Russ']
>>> 
>>> names.sort()
>>> print(names)
['Eric', 'Kevin', 'Klay', 'Kyrie', 'Lebron', 'Russ', 'Steph']
>>> names.reverse()
>>> print(names)
['Steph', 'Russ', 'Lebron', 'Kyrie', 'Klay', 'Kevin', 'Eric']

for loops

Now that we have a solid understanding of lists, we can discuss for loops, which are tightly coupled with lists. There is also some coverage of for loops in the python tutorial.

while loops continue to loop while the specified condition is True. for loops differ, and are rather similar to for loops in bash. A for loop executes the body of the loop for each element in a given list.

The general for loop syntax is:

for some_var_name in some_list :
    statement A
    statement B
    ...

In plain English, this is interpreted as “For each element in the list some_list, assign the element to the some_var_name variable and execute all of the python statements in the body sequentially.”

A very simple actual example is a follows:

>>> names = ['Russ', 'Lebron', 'Steph', 'Klay', 'Eric']
>>> for name in names:
...     print('Player: ' + name)
... 
Player: Russ
Player: Lebron
Player: Steph
Player: Klay
Player: Eric

For each element in names, the value is assigned to name and the loop body executes.

If we wanted to iterate over a series of numbers using while loops, we would do something like:

>>> i = 1
>>> while i <= 10:
...     print('i=' + str(i))
...     i += 1
... 
i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
i=9
i=10

To do a similar thing with for loops, we can generate a list of numbers and iterate over them:

>>> for i in list(range(1,11)):
...     print('i=' + str(i))
... 
i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
i=9
i=10


Write a function named is_length. This function will take two arguments. The first is named words, which will be a list of strings. The second is a number, called length.

For each word X in the words list, this function will print out will check if the word’s length is longer than length. If it is, it will print out "X" is long enough!. If not, it will print out "X" is too short!.