Lecture 8

Review

  1. How many times does "Hello World" print? for i in range(5):
        print("Hello World")
  2. What values are printed? for i in range(0, 10, 2):
        print(i)
  3. What values are printed? numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    print(numbers[0:len(numbers):2])
  4. What value is printed? letters = ['a', 'b', 'c', 'd', 'e']
    print(letters[3])
  5. What is the length of each of these lists? Are there any lists that would cause an error?
    1. a = ['a', 'b', 'c']
    2. b = ['aa', 'bb', 'cc']
    3. c = [1, 'b', 3, 'd']
    4. d = ['ant', -13.8, ['bird', 'dog'] ]

Lists and Tuples (continued)

Slicing

The slicing operation creates a new list, taking elements from the first list that the programmer specifies. You again use the square brackets, but now specify two or three values instead of just one. Separate the values with the colon (:). The general form for slicing is:

list_name[start_index:stop_index]

or

list_name[start_index:stop_index:step_size]

The start_index is the index to start slicing at. Stop slicing at the stop_index (will not include this index). The optional step_size indicates how many steps to take before picking the next element; if it is not specified, the default is 1.

Some examples:

>>> a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']
>>> a[0:5] #start at index 0 and go up to but not including index 5; no step size is specified, so defaults to 1
['a', 'b', 'c', 'd', 'e']
>>>
>>> a[0:len(a):2] #get every other element in the list
['a', 'c', 'e', 'g', 'i', 'k']
>>>
>>> #just like with the range function, if you want to go backwards, you must specify a negative step size
>>> a[5:0] #start at 5, go up to but not including 0 (with implicit step size of 1) ... you can't go from 5 to 0 by adding 1, so you get an empty list
[]
>>> a[5:0:-1] #start at 5, go up to but not including 0, step size -1
['f', 'e', 'd', 'c', 'b']
>>> #why isn't 'a' in that list?

You can leave out the start_index or the stop_index (although you still need the colons). If you leave out start_index, it defaults to 0. If you leave out stop_index, it defaults to len(list_name).

Some examples:

>>> a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']
>>> a[:5] #no start_index specified, so start at 0; go up to but not including index 5; no step_size specified, so defaults to 1
['a', 'b', 'c', 'd', 'e']
>>>
>>> #get the last 5 elements in the list:
>>> a[-5:]
['h', 'i', 'j', 'k', 'l']
>>>
>>> a[::2] #get every other element in the list
['a', 'c', 'e', 'g', 'i', 'k']
>>>
>>> a[5::-1] #start at 5, walk with a step size -1, and stop when you reach the end of the list
['f', 'e', 'd', 'c', 'b', 'a']

Slicing makes a new list and puts the elements into that new list. So, if you change the new list, the old list will not change.

>>> a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']
>>> b = a[:5]
>>> b[0] = 3
>>> b
[3, 'b', 'c', 'd', 'e']
>>> a
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']

Just like with indexing, you can do assignments to a slice. It replaces the specified part of the list with the given value.

>>> a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']
>>> a[:5] = 'z' #replace elements 0 through 4 (inclusive) with the value 'z'
>>> a
['z', 'f', 'g', 'h', 'i', 'j', 'k', 'l']
>>> #notice that it doesn't replace each element with a 'z', it replaces that whole part of the list with a 'z'
>>>
>>> a[-2:] = 'a'
>>> a
['z', 'f', 'g', 'h', 'i', 'j', 'a']
>>>
>>> #you can only do this with a step size of 1, other steps don't work
>>> a[0:6:2] = 'x'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: attempt to assign sequence of size 1 to extended slice of size 3
>>> a[6:0:-1] = 'x'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: attempt to assign sequence of size 1 to extended slice of size 6

You can also replace parts of a list with another list:

>>> a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']
>>> a[0:2] = [1, 2, 3]
>>> a
[1, 2, 3, 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']
>>>
>>> a[4:8:3] = [0, 1] #replace the elements at index 4 and 7 with the values in the list [0, 1]
>>> a
[1, 2, 3, 'c', 0, 'e', 'f', 1, 'h', 'i', 'j', 'k', 'l']
>>>
>>> #this will only work if the number of elements sliced equals the number of elements in the list being assigned
>>> a[4:8:3] = [10, 20, 30] #replace the elements at index 4 and 7 with the values in the list [10, 20, 30]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: attempt to assign sequence of size 3 to extended slice of size 2

Common List Operations

Python provides a lot of functions for working with lists (documentation). Below are some common operations.

Operation Description Example
Adding new elements to a list
list_name.append(value) Add an item to the end of the list >>> a = ['a', 'b', 'c']
>>> a.append('d')
>>> print(a)
['a', 'b', 'c', 'd']
list_name.extend(second_list) Extend list_name by appending all of the elements from second_list into it >>> a = ['a', 'b', 'c']
>>> b = [1, 2, 3]
>>> a.extend(b)
>>> print(a)
['a', 'b', 'c', 1, 2, 3]
list_name.insert(index, value) Insert an item into the specified index of the list, moving other values down to make room >>> a = ['a', 'c']
>>> a.insert(1, 'b')
>>> print(a)
['a', 'b', 'c']
list1 + list2 Create a new list by concatenating list1 and list2 together >>> a = ['a', 'b', 'c']
>>> b = [1, 2, 3]
>>> c = a + b
>>> print(c)
['a', 'b', 'c', 1, 2, 3]
Removing elements
del list_name[i] Delete element at position i from the list. Shift elements down to fill in the gap. >>> a = ['a', 'b', 'c', 'd']
>>> del a[2]
>>> a
['a', 'b', 'd']
del list_name[start_index:stop_index]
del list_name[start_index:stop_index:step_size]
Delete the elements selected by the slice. Shift elements down to fill in the gap. >>> a = ['a', 'b', 'c', 'd', 'e']
>>> del a[2:4]
>>> a
['a', 'b', 'e']
>>>
>>> a = ['a', 'b', 'c', 'd', 'e']
>>> del a[0:len(a):2]
>>> a
['b', 'd']
list_name.remove(value) Delete the first occurrence of value from the list. Shift elements down to fill in the gap. >>> a = ['a', 'b', 'c', 'a', 'b', 'c']
>>> a.remove('a')
>>> a
['b', 'c', 'a', 'b', 'c']
list_name.clear() Clear the list. >>> a = ['a', 'b', 'c', 'a', 'b', 'c']
>>> a.clear()
>>> a
[]
Searching for elements
list_name.index(value)
list_name.index(value, start_index)
list_name.index(value, start_index, stop_index)
Search for value in list_name and return the index. If start_index is given, then start at that position. If both start_index and stop_index are specified, search only the sub-list list_name[start_index:stop_index].
If value is not found, ValueError is raised.
>>> a = ['a', 'b', 'c', 'bb', 'd', 'b']
>>> a.index('b')
1
>>> a.index('b', 2)
5
>>> a.index('x')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 'x' is not in list
list_name.count(value) Returns the total number of occurrences of value in list_name >>> a = ['a', 'b', 'c', 'bb', 'd', 'b']
>>> a.count('b')
2
value in list_name True if value is in the list, False otherwise >>> a = ['a', 'b', 'c', 'dd']
>>> 'b' in a
True
>>> 'd' in a
False
value not in list_name False if value is in the list, True otherwise >>> a = ['a', 'b', 'c', 'dd']
>>> 'b' not in a
False
>>> 'd' not in a
True
Sorting elements
max(list_name) Finds the largest value in list_name. The list must contain values that can be compared! >>> a = ['a', 'b', 'c', 'bb', 'd', 'b']
>>> max(a)
'd'
>>>
>>> #numbers and strings aren't comparable
>>> a = ['a', 'b', 'c', 1, 2, 3]
>>> max(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: str() > int()
min(list_name) Finds the smallest value in list_name. The list must contain values that can be compared! >>> a = ['a', 'b', 'c', 'bb', 'd', 'b']
>>> min(a)
'a'
>>>
>>> #numbers and strings aren't comparable
>>> a = ['a', 'b', 'c', 1, 2, 3]
>>> min(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: str() > int()
list_name.sort() Puts list_name in sorted order The list must contain values that can be compared! >>> a = ['d', 'b', 'c', 'a', 'e']
>>> a.sort()
>>> print(a)
['a', 'b', 'c', 'd', 'e']
Lists and Numbers
sum(list_name) Adds up all the numbers in list_name and returns the sum. The list must contain numbers. >>> a = [13, 8, -5, 6.89, -2.09]
>>> total = sum(a)
>>> print(total)
20.8
Lists and Strings
string.split()
string.split(delim)
Splits the string into a list. If delim is specified, it uses delim as the separator in the string. If delim is not specified, then whitespace (e.g. space, tab, newline) is used. >>> a = 'Splits the string into a list.'
>>> a.split() #no delimiter, so use whitespace
['Splits', 'the', 'string', 'into', 'a', 'list.']
>>>
>>> a = '12.3, 14.8, 9.2, 12.6'
>>> numbers = a.split(',') #split on ','
>>> print(numbers)
['12.3', ' 14.8', ' 9.2', ' 12.6']
>>> #why are there spaces before each number after the first one?
>>>
>>> numbers = a.split(', ') #split on comma, followed by space
>>> print(numbers)
['12.3', '14.8', '9.2', '12.6']
>>> #notice that now each element is a string representation of a number
sep.join(list_name) Joins a list of strings into a single string with each element in the list separated by sep (a string). >>> a = ['Splits', 'the', 'string', 'into', 'a', 'list.']
>>> ' '.join(a)
'Splits the string into a list.'

How do you think you'd find the second largest value in a list?

When introducing for loops, one example was counting the number of vowels in text (program duplicated below). How could we simplify the code by using a list?

value = input("Enter text: ")
count = 0 #number of vowels in value
for letter in value:
    if letter == 'a' or letter == 'e' or letter == 'i' or letter == 'o' or letter == 'u':
        count += 1

print("There are", count, "lowercase vowels in the text you entered.")

How would you find the index of the largest element in the list?

The index method only finds one occurrence. Write code that finds the index of all occurrences of a value. Store the indices in a list.

Given a list of numbers, add up all of the numbers at even positions. Try writing this in one line of code.

The split function breaks a string into a list of strings. What if that string were a list of numbers (e.g. '12.3, 14.8, 9.2, 12.6'). How could you convert it into a list of numbers?

The join function converts a list of strings into one string. How could you use join to convert a list of numbers into a string?

List Comprehension

To answer the last two questions in the section above, you need to write a loop (preferably a for loop). Lists and for loops go together so often, the Python language designers created list comprehension to streamline the creation of new lists using for loops.

Using list comprehension, you can transform a for loop like this one:

numbers = [1, 2, 3, 4, 5]
squared = []
for val in numbers:
    squared.append(val*val)

into this:

numbers = [1, 2, 3, 4, 5]
squared = [val*val for val in numbers]

In fact, you can simplify this even more:

numbers = range(1, 6) #note: numbers doesn't actually hold a list, use the list function if you want an actual list
squared = [val*val for val in numbers]

If you don't actually need the numbers list, you can simplify it to:

squared = [val*val for val in range(1, 6)]

You can also use an if statement in list comprehension, allowing you to convert:

#This program removes all the words starting with 't' from the list:
words = ["This", "program", "removes", "all", "the", "words", "starting", "with", "'t'", "from", "the", "list"]
non_t_words = []
for word in words:
    if not word.startswith('t'):
        non_t_words.append(word)

into:

#This program removes all the words starting with 't' from the list:
words = ["This", "program", "removes", "all", "the", "words", "starting", "with", "'t'", "from", "the", "list"]
non_t_words = [word for word in words if not word.startswith('t')]

List comprehension can be used in creative ways, such as rewriting the program from above, where we counted the number of lowercase vowels in a user-provided string. We're able to convert:

value = input("Enter text: ")
count = 0 #number of vowels in value
for letter in value:
    if letter == 'a' or letter == 'e' or letter == 'i' or letter == 'o' or letter == 'u':
        count += 1

print("There are", count, "lowercase vowels in the text you entered.")

into:

value = input("Enter text: ")
count = sum([1 for letter in value if letter in ['a', 'e', 'i', 'o', 'u']])
print("There are", count, "lowercase vowels in the text you entered.")

or (note the change of sum to len):

value = input("Enter text: ")
count = len([1 for letter in value if letter in ['a', 'e', 'i', 'o', 'u']])
print("There are", count, "lowercase vowels in the text you entered.")

The list Function

There are times where you will want to convert something into a list. We haven't seen a lot of data structures yet, but a lot of them can be converted into a list using the list "function" (technically, it's a callable class, but it's most often used as a function). The list function takes any iterable object. Iterable objects are objects that we can do this to:

for val in iterable_object:
    #do something

So far, we've see these iterable objects:

When we use the range function, we get back a range object. Sometimes we want an actual list of the integers represented by the range. The example below shows how to convert a range object into a list.

>>> zero_thru_ten = range(11)
>>> print(type(zero_thru_ten))
range
>>> print(zero_thru_ten)
range(0, 11)
>>>
>>> zero_thru_ten = list(zero_thru_ten)
>>> print(type(zero_thru_ten))
list >>> print(zero_thru_ten)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Tuples

Tuples are almost like lists, except they can't change their values. So once a tuple is created, you cannot add new elements to it nor can you change the value of existing elements. To create a tuple:

You can also convert an iterable type into a tuple using the tuple "function":

>>> numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> unchangeable = tuple(numbers)
>>> print(unchangeable)
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
>>> print(type(unchangeable))
tuple
<< Previous Notes Daily Schedule Next Notes >>