We have worked with lists, which hold data sequentially; to access elements, we can use their indices. In a way, an index is a unique identifier associated with a piece of data. For example, if we think of a list as a row of seats in a theater, then we can direct an audience member to seat 5 without them wondering where they should go. The number 5 uniquely identifies the seat.
We don't always have a natural sequential ordering associated with data. In this topic, we'll look at a data structure known as a map or an associative array. Python refers to this as a dictionary. You may want to think of it like a spreadsheet, where the first column holds unique keys and the second column holds associated values.
def printTreeInfo( fruitTree ):
""" Given a dictionary that stores the info for a tree,
print out its data. """
# access values by keys using the [] operator
print( "Your " + fruitTree["type"] + " tree is " + str( fruitTree["height"] ) + " feet tall." )
if fruitTree["hasFruit"]:
print( "It has fruit -- time to make a pie!" )
else:
print( "No fruit yet... be patient...")
# use a dictionary to store info about a fruit tree
appleTree = { "type" : "apple", "height" : 10, "hasFruit" : False }
# invoke a function to query the dictionary for data
printTreeInfo( appleTree )
# update a stored key
appleTree[ "hasFruit" ] = True
# print the updated tree
printTreeInfo( appleTree )
A dictionary provides a mapping from a key to a value. For example, here is a price list for a drink shop.
Iced tea $4
Hot chocolate $3
Coffee $4
Juice box $2
Like lists, there are different ways to initialize a dictionary. Notice in the sample code below:
We use curly braces {} to denote the dictionary
We use the keyword dict as the type
We can initialize an empty dictionary with a pair of curly braces (and nothing inside)
We can initialize a dictionary with starting key-value entries using the syntax key : value and separating the entries with commas.
emptyDictionary:dict = {}
priceList:dict = { "Iced Tea":4,
"Hot chocolate":3,
"Coffee":4,
"Juice box":2 }
We can access elements in the dictionary using the square bracket notation (that we also use with lists). For example, to access the price of a coffee, we use the expression priceList["coffee"].
Notice how we use square brackets [] to access a value in a dictionary, but the value inside the square brackets is the name of the key whose value we want to look up.
emptyDictionary:dict = {}
priceList:dict = { "Iced Tea":4,
"Hot chocolate":3,
"Coffee":4,
"Juice box":2 }
coffeePrice:int = priceList["Coffee"]
print( f"A coffee costs ${coffeePrice}" )
The snippet above outputs:
A coffee costs $4
We can update an existing entry in the dictionary using the square bracket notation (again, similar to lists) to access the entry and assign it a new value. For example, the following will update the price of a coffee:
emptyDictionary:dict = {}
priceList:dict = { "Iced tea":4,
"Hot chocolate":3,
"Coffee":4,
"Juice box":2 }
coffeePrice:int = priceList["Coffee"]
print( f"A coffee costs ${coffeePrice}" )
priceList["Coffee"] = 5
coffeePrice = priceList["Coffee"]
print( f"A coffee now costs ${coffeePrice}" )
The above snippet of code prints out:
A coffee costs $4
A coffee now costs $5
We can add a new entry to the dictionary using the same notation, but with a key that is not in the dictionary yet. For example, the following adds a new entry to the dictionary.
emptyDictionary:dict = {}
priceList:dict = { "Iced tea":4,
"Hot chocolate":3,
"Coffee":4,
"Juice box":2 }
priceList["Smoothie"] = 6
Just as with lists, we sometimes want to walk over all the entries in a dictionary. The for...in construct lets us iterate over all the keys in a dictionary; refer to this sample code:
priceList:dict = { "Iced tea":4,
"Hot chocolate":3,
"Coffee":4,
"Juice box":2 }
for item in priceList:
# access the dictionary to get the value associated to this key
price:int = priceList[item]
# print it out
print( f"The price of {item} is ${price}.")
This prints out:
The price of Iced tea is $4.
The price of Hot chocolate is $3.
The price of Coffee is $4.
The price of Juice box is $2.
We can also iterate over the values by using an instance method that accesses just the value data. Check out this sample code:
priceList:dict = { "Iced tea":4,
"Hot chocolate":3,
"Coffee":4,
"Juice box":2 }
for price in priceList.values():
# print it out
print( f"${price}.")
This prints out just the values, with no guarantee of the order in which the entries are traversed.
$4.
$3.
$4.
$2.
Notice that if we have a key, we can get the associated value from the dictionary, but if we have a value, there is no clear way to get the associated key. One reason for that is that while each key-value entry has a unique key, it is possible for there to be many key-value pairs that have the same value. In our running example, both the "Iced tea" and "Coffee" map to the value of 4.
priceList:dict = { "Iced tea":4,
"Hot chocolate":3,
"Coffee":4,
"Juice box":2 }
Note that, if we try to access an entry for a key and there is no associated entry, we will get a KeyError. It is often a good idea to check if an entry exists before accessing it. We can do that with the in operator, as in the following sample code:
priceList:dict = { "Iced Tea":4,
"Hot chocolate":3,
"Coffee":4,
"Juice box":2 }
order:str = input( "What drink would you like the price of? " )
if order in priceList:
print( f"The price of {order} is ${priceList[order]}.")
else:
print( f"Sorry, we don't serve {order}.")
If we enter "Coffee" when prompted, we will see:
The price of Coffee is $4.
But, if we enter "Bubble tea" when prompted, we will see:
Sorry, we don't serve Bubble tea.