In this lab, you’ll practice working with lists and dictionaries. Pieces of this lab are based on problems from Introduction to Python Introducing Lists and Dictionaries, and it was adapted for this course in June 2018 by R. Jordan Crouser, and updated by Alicia M. Grubb in Spring 2019/2020.
In order to be sucessful in computer science, an important skill that you must develop is understanding how to implement and develop a specification, and knowing when you can take liberty with the specification. You also need to distingush between implementing and developing a specification. In the course work for CSC111, we ask for some things very precisely. It is important that you read every word of lab and assignment descriptions. Misreading or ignoring directions will result in incorrect software/code.
Take a few minutes and introduce yourself to your lab partner. Answer the questions: “Smarties vs. M&Ms?”, “Rockets vs. Smarties?”, “Mars/Milky Way vs Snickers vs Twix”
Setup: We added prompts to remind you to switch driver/navigator roles, but feel free to switch more frequently or mid task.
Note: If the navigator is not comfortable reading out loud, both partners should read over this section independently.
A list
is a collection of items. In general, these items should be related in some way (although there are no restrictions on what can be stored in a python list
).
list
In Python, we define a list
using square brackets. To define a list, you give the name of the list
, the equals sign, and the values you want to include in your list
within square brackets (separated by commas). Because lists
are collections of objects, it is good practice to give them a plural name, e.g.
dogs = ['border collie', 'australian cattle dog', 'labrador retriever']
If you want your code to look a little neater, you can hit return
after each comma. IDLE
will indent automatically:
dogs = ['border collie',
'australian cattle dog',
'labrador retriever']
item
in a listJust like letters in a string, items in a list
are identified by their position in the list
(starting with zero). This will almost certainly trip you up at some point. Programmers even joke about how often we all make “off-by-one” errors, so don’t feel bad when you make this kind of error.
To access the first element in a list
:
first_dog = dogs[0]
print(first_dog)
The number in parentheses is called the index
of the item. Because lists
start at zero, the index
of an item
is always one less than its position in the list
. So to get the second item
in the list
, we need to use an index of 1:
second_dog = dogs[1]
print(second_dog)
You can probably see that to get the last item
in this list
, we would use an index
of 2. This works, but it would only work because our list
has exactly three items
. To get the last item
in a list
, no matter how long the list
is, you can use an index
of -1:
last_dog = dogs[-1]
print(last_dog)
This syntax also works for the second to last item
, the third to last, and so forth. However, as with strings, you can’t use a negative number larger than the length of the list
:
nonexistant_dog = dogs[-4] # error
lists
Looping is one of the most important concepts related to lists
. You can have a list
with a million items in it, and in three lines of code you can write a sentence for each of those million items. Make sure you take the time to understand this section!
We can use a loop
to access each of the elements in a list
one by one:
for dog in dogs:
print(dog)
Let’s break this down:
for
tells Python to get ready to use a loop.dog
(with no “s” on it) is a temporary placeholder variable. This is the variable that Python will place each item
in the list
into, one at a time.dog
will be ‘australian cattle dog’.dog
will be ‘labrador retriever’.list
, and the loop will end.At this point you should switch driver/navigator roles.
list
OperationsBecause lists
are mutable, you can change the value of any element in a list
if you know the position of that item.
dogs[0] = 'australian shepherd'
print(dogs)
If you want to find out the position of an element in a list, you can use the index()
method.
print(dogs.index('australian cattle dog'))
This method returns a ValueError if the requested item
is not in the list, e.g.
print(dogs.index('poodle'))
item
is in a list
You can test whether an item
is in a list
using the same in
keyword that we used in for...in
loops, resulting in True
if the item
is present and False
otherwise:
print('australian cattle dog' in dogs)
print('poodle' in dogs)
We can add an item
to a list
using the append()
method. This method adds the new item
to the end of the list
.
dogs.append('poodle')
for dog in dogs:
print(dog.title() + "s are cool.")
items
into a list
We can also insert items
anywhere we want in a list
using the insert()
method. We specify the index
into which we want to insert the item
, and everything from that point on is shifted one position to the right. In other words, the index of every item
after the new item
is increased by one:
dogs = ['border collie',
'australian cattle dog',
'labrador retriever']
dogs.insert(1, 'poodle')
print(dogs)
Note that you have to give the position of the new item
first, and then the value of the new item. If you do it in the reverse order, you will get an error.
If you know the position of an item
in a list
, you can remove that item using the del
command (short for “delete”). To use this approach, give the command del
and the name of your list
, with the index of the item
you want to remmove in square brackets:
# Remove the first dog from the list.
del dogs[0]
print(dogs)
You can also remove an item
from a list
if you know its value. To do this, we use the remove()
function. Give the name of the list
, followed by the method remove
with the value of the item you want to remove inside the parentheses. Python looks through your list
, finds the first item with this value, and removes it:
dogs = ['border collie', 'australian cattle dog', 'labrador retriever']
# Remove australian cattle dog from the list.
dogs.remove('australian cattle dog')
print(dogs)
Note, however, that only the first item with this value is removed. If you have multiple items with the same value, you will have some items with this value left in your list.
letters = ['a', 'b', 'c', 'a', 'b', 'c']
# Remove the letter a from the list.
letters.remove('a')
print(letters)
Want to check out all the other methods
available on lists
? Read the documentation!
At this point you should switch driver/navigator roles.
lab5p1.py
in which you and your partner will work. Add the usual header, including both your names.list
called songs
.while
loop to ask the user to enter the titles of their favorite songs (one at a time). End the loop when the user types “DONE”..append()
method to add each song title to songs
..sort()
the list
and print out the songs in a nicely-formatted way (you choose how it looks).At this point you should switch driver/navigator roles.
Note: If the navigator is not comfortable reading out loud, both partners should read over this section independently.
Dictionaries are another way to store information that is connected in some way. Dictionaries store information in key-value pairs, so that any one piece of information in a dictionary is connected to at least one other piece of information. If we want, we can define them explicitly using key:value
pairs and curly braces:
python_words = {'list': 'A collection of values that are not connected, but have an order.',
'dictionary': 'A collection of key-value pairs.',
'function': 'A named set of instructions that defines a set of actions in Python.',
}
To add a new key-value pair, you give the dictionary name followed by the new key in square brackets, and set that equal to the new value. We will show this by starting with an empty dictionary, and re-creating the dictionary from the example above.
# Create an empty dictionary.
python_words = {}
# Fill the dictionary, pair by pair.
python_words['list'] ='A collection of values that are not connected, but have an order.'
python_words['dictionary'] = 'A collection of key-value pairs.'
python_words['function'] = 'A named set of instructions that defines a set of actions in Python.'
Remember: dictionaries do not store their information in any particular order, so you may not get your information back in the same order you entered it.
We can get individual items out of the dictionary by giving the dictionary’s name, followed by the key in square brackets:
print("\nWord: {0}".format('list'))
print("Meaning: {0}".format(python_words['list']))
print("\nWord: {0}".format('dictionary'))
print("Meaning: {0}".format(python_words['dictionary']))
print("\nWord: {0}".format('function'))
print("Meaning: {0}".format(python_words['function']))
This code looks pretty repetitive, and it is. Dictionaries have their own for
loop syntax, but since there are two kinds of information in dictionaries, the structure is a bit more complicated than it is for lists. Here is how to use a for
loop with a dictionary:
# Print out the items in the dictionary.
for word, meaning in python_words.items():
print("\nWord: {0}".format(word))
print("Meaning: {0}".format(meaning))
The output is identical, but we did it in 3 lines instead of 6. If we had 100 terms in our dictionary, we would still be able to print them out with just 3 lines.
The only tricky part about using for
loops with dictionaries is figuring out what to call those first two variables. The general syntax for this for
loop is:
for key_name, value_name in dictionary_name.items():
print(key_name) # The key is stored in whatever you called the first variable.
print(value_name) # The value associated with that key is stored in your second variable.
If you attempt to access an entry that is not in the dictionary, Python will return an error. For example,
python_words['noItem']
Will return the following error:
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
KeyError: 'noItem'
To check if an entry is in the dictionary use the .get(key)
function, which returns the value or None
if the key is not in the dictionary. For example:
print(python_words.get('noItem'))
print(python_words.get('list'))
will have the following output:
None
A collection of values that are not connected, but have an order.
At this point you should switch driver/navigator roles.
At some point you may want to modify one of the values in your dictionary. Modifying a value in a dictionary is similar to modifying an element in a list. You give the name of the dictionary and then the key in square brackets, and set that equal to the new value.
# Clarify one of the meanings.
python_words['dictionary'] = 'A collection of key-value pairs. Each key can be used to access its corresponding value.'
print('dictionary:', python_words['dictionary'])
You may want to remove some key-value pairs from one of your dictionaries at some point. You can do this using the same del
command you learned to use with lists. To remove a key-value pair, you give the del command, followed by the name of the dictionary, with the key that you want to delete. This removes the key and the value as a pair.
python_words = {'list': 'A collection of values that are not connected, but have an order.',
'dictionary': 'A collection of key-value pairs.',
'function': 'A named set of instructions that defines a set of actions in Python.',
}
# Show the current set of words and meanings.
print("\n\nThese are the Python words I know:")
for word, meaning in python_words.items():
print("\nWord: {0}".format(word))
print("Meaning: {0}".format(meaning))
# Remove the word 'list' and its meaning.
del python_words['list']
# Show the current set of words and meanings.
print("\n\nThese are the Python words I know:")
for word, meaning in python_words.items():
print("\nWord: {0}".format(word))
print("Meaning: {0}".format(meaning))
If you were going to work with this code, you would certainly want to put the code for displaying the dictionary into a function. Let’s see what this looks like:
def show_words_meanings(python_words):
# This function takes in a dictionary of python words and meanings,
# and prints out each word with its meaning.
print("\n\nThese are the Python words I know:")
for word, meaning in python_words.items():
print("\n{0}: {1}".format(word, meaning))
python_words = {'list': 'A collection of values that are not connected, but have an order.',
'dictionary': 'A collection of key-value pairs.',
'function': 'A named set of instructions that defines a set of actions in Python.',
}
show_words_meanings(python_words)
# Remove the word 'list' and its meaning.
del python_words['list']
show_words_meanings(python_words)
This is starting to look like much more realistic code.
At this point you should switch driver/navigator roles.
lab5p2.py
in which you and your partner will work. Add the usual header, including both your names.dictionary
with the mountain names as keys
, and the elevations as values
.keys
of your dictionary
.values
of your dictionary
.At this point you should switch driver/navigator roles.
Making a YouTube playlist with lists
and dictionaries
.
Create a new file called lab5p3.py
in which you and your partner will work. Add the usual header, including both your names.
Review and add the following code to your file.
import webbrowser
from time import sleep
def playNewSong():
# Ask for info about song
title = input("Song title: ")
url = input("YouTube video: ")
duration = input("Video duration (MM:SS): ")
# Convert 'duration' string into seconds
time = duration.split(":")
total_seconds = int(time[0])*60 + int(time[1])
print("Now playing", title)
sleep(2) # Wait 2 seconds before opening the video
webbrowser.open(url)
sleep(total_seconds) # Wait until the video is over
print("Song is over!")
This function asks the user to enter a song title, youtube link, and the duration of the video. It then prints the song information, launches a browser window containing the YouTube video (which should play automatically), and then goes to sleep for the duration of the song.
song
that has keys title
, url
, and duration
list
called playlist
(this will be a list
of dictionaries
) End the loop when the user types DONE
.playNewSong()
(above), write a new function called playSong(title, url, duration)
that plays a single song given the parameters (title, url, duration).playSongs(song_dict)
that takes a songs dictionary and makes a random playlist and plays all the songs in the playlist. This function should call playSong
and be called after the user enters DONE
.lab5p1.py
, lab5p2.py
, and lab5p3.py
files before the end of the day.If you have time, we encourage you to get started on your homework assignment in lab this week.
Note: this section is included because people have been asking about it. If you’re already feeling a little shaky on lists, don’t worry. For now, it is good enough to know they exist, and to recognize them when you see them. If you like them, go ahead and start trying to use them now.
Let’s consider how we might make a list of the first ten square numbers. We could do it like this:
# Store the first ten square numbers in a list.
# Make an empty list that will hold our square numbers.
squares = []
# Go through the first ten numbers, square them, and add them to our list.
for number in range(1,11):
new_square = number**2
squares.append(new_square)
# Show that our list is correct.
for square in squares:
print(square)
This should make sense at this point. If it doesn’t, go over the code with these thoughts in mind:
list
called squares
that will hold the values we are interested in.range()
function, we start a loop
that will go through the numbers 1-10.list
squares
.list
and print out each value
Now let’s make this code more efficient. We don’t really need to store the new square in its own variable new_square; we can just add it directly to the list of squares:
# Store the first ten square numbers in a list.
# Make an empty list that will hold our square numbers.
squares = []
# Go through the first ten numbers, square them, and add them to our list.
for number in range(1,11):
squares.append(number**2)
# Show that our list is correct.
for square in squares:
print(square)
List comprehensions allow us to collapse the first three lines of code into one line. Here’s what it looks like:
# Store the first ten square numbers in a list.
squares = [number**2 for number in range(1,11)]
# Show that our list is correct.
for square in squares:
print(square)
It should be pretty clear that this code is more efficient than our previous approach, but it may not be clear what is happening. Let’s take a look at everything that is happening in that first line:
We first define a list
called squares
.
Look at the second part of what’s in square brackets:
for number in range(1,11)
This sets up a loop that goes through the numbers 1-10, storing each value in the variable number
. Now we can see what happens to each number
in the loop:
number**2
Each number is raised to the second power, and this is the value that is stored in the list we defined. We might read this line in the following way:
squares = [raise number to the second power, for each number in the range 1-10]