Intro to Programming: Dictionaries in Python

Welcome back to the next article in my Intro to Programming series. Today we'll talk about another powerful data type in Python: the dictionary.
By Ciprian Stratulat • Dec 14, 2021

Welcome back to the next article in my Intro to Programming series. Today we'll talk about another powerful data type in Python: the dictionary.

 

Python Dictionaries

Unless you've used other programming languages before, the word “dictionary” might make you think of a few things. One type of dictionary is a book that translates words between languages, like a Spanish to English dictionary. And that's not a bad analogy in this case. We can actually start with it to understand dictionaries in Python.

Here I have a small dictionary. My dictionary maps the English words “morning”, “afternoon”, and “evening” to their Spanish counterparts. (I translated these using Google; apologies if they're not the most accurate!) A dictionary data structure like this example is useful for storing certain types of data.

Word translations is a great example, but we could also have a dictionary that does something like map fruits to their market price per pound.

Or, we could have a dictionary that maps countries to their capital cities. These examples are just a few of the functions of dictionaries in Python.

More precisely, a Python dictionary is a collection of object pairs.

The item being translated is called the key and the translation is the value. We can rephrase this to say that a dictionary is a collection of key-value pairs.

You may also hear dictionaries referred to as “mappings”. That's because dictionaries map, or associate, key objects to value objects.

In Python, we wrap dictionaries in curly braces. Curly braces indicate to the Python interpreter that we're talking about a dictionary, as opposed to a list, for example. For instance, we took the earlier market prices mapping and turned it into a Python dictionary. As you can see, the dictionary looks the same as before, except that now we have curly braces around it. The names of the fruit are between quotes because they are strings. Also similar to lists, we separate these pairs by commas to ensure the Python interpreter understands where one pair ends and the next pair begins. Note that we put colons between the key and the value inside a pair. These are important. Don't forget the colons!

Next we’ll look at some of the key differences between Python dictionaries and lists, as well as when to use each in your scripts.

 

Dictionaries vs. Lists

Important differences exist between Python dictionaries and lists. Let’s explore them, as well as appropriate use cases for each data type.

We’ll begin with an easy one. Python dictionaries are not ordered and they cannot be sorted, whereas lists are ordered and sorted. What this means is that with dictionaries, the order of the pairs doesn’t matter. In fact, if you print a dictionary multiple times, you might get the pairs returned in a different order than you input them.

For example, these two images are of the same dictionary. With dictionaries, the order of the key-value pairs doesn't matter and there's no way to order the pairs. This may be a bit counterintuitive because in a language dictionary, for example, words are ordered alphabetically. However, in Python, the pairs are not ordered.

Compare this to lists. These two lists are not identical. These two lists contain the same objects, but, because the objects are in a different order, Python actually considers them different lists. This is important, so remember this distinction.

The next difference between dictionaries and lists is related to the not ordered nature of dictionaries. Because dictionaries are not ordered collections, you can't use indexing and slicing to inquire about data. Dictionaries have no concept of a pair at index 0, for example, because it's not guaranteed what that pair might be. At any given moment, the pair could be apples : 2.99, or oranges : 3.99. Because the locations of pairs in dictionaries are fluid, dictionaries don't support indexing and slicing.

So how do we get data out of dictionaries? We retrieve our desired data using the key name. I'll show you how.

Let's jump into a new Jupyter notebook and write some code to make sense of all this.

First, let's define the dictionary we saw earlier. We'll call this dictionary market_prices. In it we have prices by the pound for apples, avocados, and oranges. If we output this, we see the dictionary. We can check the data type using the type function and see that Python returns dict, which stands for dictionary. The print function also works with dictionaries. We can write print(market_prices) and we will get our dictionary. Similarly, the len function also works. If we write len(market_prices), Python returns 3, which is the number of pairs in the dictionary.

 

# let's define the dictionary
market_prices = { 'apples': 2.99, 'avocados': 4.99, 'oranges': 3.99 }

# let's see what the dictionary contains
# the output should be {'apples': 2.99, 'avocados': 4.99, 'oranges': 3.99}
print(market_prices)

# let's check our data type
# the output should be dict
type(market_prices)

# let's check the length of this dictionary using the len function
# the output should be 3
len(market_prices)

 

Just like lists, dictionaries can be empty. If we have no key-value pairs inside a dictionary, we only type the curly braces, like so: d = {}. And we can easily check that the variable d is, in fact, of type dictionary by using type(d) and seeing that it returns dict. And, of course, the length of an empty dictionary is 0. We can check that using len(d), which returns 0.

 

# let's define an empty dictionary
d = {}

# let's make sure that d is a dictionary
# the output should be dict
type(d)

# let's check the length by using the len fuction
# the output should be 0
len(d)

 

Now, let’s access data inside our dictionary. Typically, in a dictionary, we’re interested in getting the value from a key-value pair. Think about a language dictionary. We typically know the word we want translated, but we don’t know the translation. It’s the same use case with a Python dictionary. Most often we’ll know the key, but not the value. However, we can use the key to get the value.

To do so we use a similar notation to indexing. To use a key to return a value, we use the same square brackets used in indexing. But, instead of specifying an index between the square brackets, with dictionaries we write the key like this: market_prices['apples']. This input returns 2.99. Let's try another. If we want the price of oranges, we write market_prices['oranges'] and we get 3.99. We can also get the price of avocados: market_prices['avocados'] gives us 4.99.

 

# we can find a value in a dictionary by using a key
# let's find the price, or value, of the key 'apples'
# the output should be 2.99
market_prices['apples']

# let's find the price of oranges
# the output should be 3.99
market_prices['oranges']

# and now the price of avocados
# the output should be 4.99
market_prices['avocados']

 

Dictionaries support a variety of data types for keys and values, and not just strings and floating-point numbers. Let's look at an example we saw when we learned about lists. We previously had a list that stored some attributes about a person. More precisely, we had person = ['blue', 5.7, 120.5, ['Amsterdam', 'Barcelona'], '111-00-0000', 'S000001']. In our list example, we said this meant this person’s eye color was blue, height was 5.7 feet, and so on.

# our list describing a person
person = ['blue', 5.7, 120.5, ['Amsterdam', 'Barcelona'], '111-00-0000', 'S000001']

 

In the previous example, we read data from this list variable using indexes. At the time, that method worked. However, it’s not an ideal method to use because it forces us to remember what each object means. For example, we had to remember that the string “blue” meant eye color, and not the person's favorite color. Similarly, we had to remember, somehow, that the two cities listed were favorite travel destinations, as opposed to, say, cities where the person grew up. So, you see, in a list of this kind, the meaning of the data isn't explicit. It's implied. And that's a problem because if you revisit this code months later, it's possible by that time you’ve forgotten what each of these objects stood for, without making notes somewhere.

A dictionary is a much better data structure to use for something like this. In a dictionary, the key is the name of the attribute and the value is the value of that attribute. Once again, let me show you.

Let's define a person attributes dictionary and call it person_attrs for short. We know it's a dictionary so we’ll use the curly braces. We’ll start with the first attribute: eye color. In our dictionary, we write 'eye_color': 'blue'. Notice that the keys are strings, so we must use quotes. Next is the height: 'height': 5.7. Next, the weight: 'weight': 120.5. Next, the top vacation cities, or ‘vacation_cities':['Amsterdam', 'Barcelona']. And finally, the IDs: ids: ['111-00-0000', 'S000001']. Notice that both the top vacation cities and the IDs are lists because each of these keys contains more than one value.

 

# let's define our dictionary
person_attrs = {'eye_color': 'blue', 'height': 5.7, 'weight': 120.5, 'vacation_cities': ['Amsterdam', 'Barcelona'], 'ids': ['111-00-0000', 'S000001']}

 

Now, if we want to get the eye color for this person, we can write person_attrs['eye_color']. Python returns blue. Compare that to what we did when we used lists: person[0]. If you look back at this code months from now, the dictionary version will be much easier to understand than the list version. The 0 in the list version is what we call a hard-coded index. Hard-coding is generally not ideal because it makes code harder to change and harder to understand.

 

# in the dictionary, we can look up the eye color using the key
# the output should be 'blue'
person_attrs['eye_color']

# in the list, we have to remember the index of the eye color value
# the output should still be 'blue' 
person[0]

 

That is not to say that dictionaries are always better than lists. They both have different use cases in which one is better than the other. The more you write code, the easier it'll be for you to pick the right data type in each situation. This last example is one where you could use either a list or a dictionary, but a dictionary makes the code easier to read and understand.

 

Nested Dictionaries

In this section, we'll explore the concept of a dictionary inside another dictionary. In Python, this is called a nested dictionary.

Let’s return again to our person attributes dictionary. We can make one more improvement to it. If you're following along in a Jupyter notebook, can you can figure it out? Let's print out the dictionary again, so we can see it better.

 

# let's see how we can improve our dictionary
# hint: look at the IDs list
print(person_attrs)

# output should be {'eye_color': 'blue', 'height': 5.7, 'ids': ['111-00-0000', 'S000001'], 'vacation_cities': ['Amsterdam', 'Barcelona'], 'weight': 120.5}

 

Look at the IDs section. The ID numbers make up a list. By their formats, the first number appears to be a US Social Security number and the second to be a driver's license. Say we want to get the driver's license part of this dictionary. How would we do that? To begin, let's first get all of the IDs. We can do that by running person_attrs['ids']. The result is a list. We remember from lists that we can use indexing to get an item from a list at a certain index position. In this case, the driver's license number is the second item in the list, at index position 1 (because in programming we start counting at 0). So, to only return the driver's license number, we need to run person_attrs['ids'][1].

 

# let's use the key to access our list of ids
# the output should be ['111-00-0000', 'S000001']
person_attrs['ids']

# now, let's use an index to access the driver's license number from the list of ids
# the output should be 'S000001'
person_attrs['ids'][1]

 

This method works, but we have the same issue again. Namely, we have to remember that the driver's license is at index position 1. In this instance, the index number 1 might as well be a magic number—it doesn't really mean anything to us. So, what do we do? We can turn the IDs list into a dictionary.

To do so, I'll copy the whole person_attrs dictionary. Then, I’ll change the IDs key. Instead of mapping it to a list, let's map it to a dictionary. Remember, we use curly braces for dictionaries. We also need key names. Let's call the first key 'ssn' and map it to the Social Security number. We’ll call the second one 'license_number'. Let’s check the type of the value mapped to the IDs key. If I run type(person_attrs['ids']), I see that it's a dictionary now.

 

# let's change the IDs list to a dictionary
# we can use the keys 'ssn' and 'license_number' 
person_attrs = { 'eye_color': 'blue', 'height': 5.7, 'weight': 120.5, 'vacation_cities': ['Amsterdam', 'Barcelona'], 'ids': {'ssn': '111-00-0000', 'license_number': 'S000001'}}

# let's check the type of value mapped to the IDs key
# the output should be dict
type(person_attrs['ids'])

 

Making the IDs into a dictionary makes accessing the data more intuitive. Now, if we run person_attrs['ids'], we get the dictionary of ids. And if we append ['license_number'] by writing person_attrs['ids']['license_number'], we get the license number. If we want the Social Security number, we run person_attrs['ids']['ssn'].

 

# we can now get the IDs dictionary
# the output should be {'license_number': 'S000001', 'ssn': '111-00-0000'}
person_attrs['ids']

# or the specific license number
# the output should be 'S000001'
person_attrs['ids']['license_number']

# or the Social Security number
# the output should be '111-00-0000'
person_attrs['ids']['ssn']

 

This notation may be a bit confusing at first, but don’t be discouraged by it. Try to break it down and read it from left to right. Using the direction left to right is important. If you read code right to left, it won't make much sense. Let's try another example that's a bit more complex.

Let's create a dictionary called d and set it equal to { 'prices': [{'apple': 2.99, 'oranges': 3.99}] }. This dictionary has one key, called prices, which is mapped to a list. The list is made up of a single item, which is also a dictionary. This dictionary has two keys: one called 'apple', which is mapped to 2.99, and one called 'oranges', which is mapped to 3.99. Knowing the structure of our new dictionary d, how do we get the price for oranges?

 

# let's create a new dictionary for prices
d = { 'prices': [{'apple': 2.99, 'oranges': 3.99}] } 

# let's get the value for the key 'prices'
# output should be [{'apple': 2.99, 'oranges': 3.99}]
print(d['prices'])

 

First, we know that all prices are in the list mapped to the key named prices. Running d['prices'] will return that list. You may notice that in order to get to the price for oranges, we first need to access the dictionary inside this list. How do we do that? We use list indexes: d['prices'][0]. This works because the list has a single item, which is the dictionary we're interested in, at index location 0. This should start looking familiar. Further, if we use the 'oranges' key, we’ll get what we need: d['prices'][0]['oranges'] returns 3.99.

 

# let's get the item at index 0 from the list associated with the key 'prices'
# the output should be {'apple': 2.99, 'oranges': 3.99}
d['prices'][0]

# then we can use the key 'oranges' to find the value associated with this key
# the output should be 3.99
d['prices'][0]['oranges']

 

These chained indexes can be as long as you need them to be. Keep appending square brackets, going deeper inside your data, until you get what you need. In my experience, programming beginners can struggle with this quite a bit, so spend some time and create your own dictionaries. Practice accessing various parts of them.

Here's another cool thing about Python: the result of running the statement d['prices'][0]['oranges'] is just a number. More precisely, it's the number 3.99. We know that we can multiply a number, among other operations. So, if I want the cost for 2 pounds of oranges, I can calculate that in one line using d['prices'][0]['oranges'] * 2. The result yields 7.98.

 

# we can easily compute the value for two pounds of oranges
# the output should be 7.98
d['prices'][0]['oranges'] * 2

 

When working with statements like these, keep in mind that the Python interpreter does the calculation and then regards the statement as the result of the calculation. In other words, Python replaces the original statement with actual values. With more programming experience, you’ll start looking at these statements in the same way. Instead of notations, you’ll begin to see lists, numbers, and strings—as well as whatever their values may be.

 

Add & Remove Pairs from Dictionaries

Next, let’s look at adding and removing pairs from a dictionary.

We saw that with lists we can use append to add new items. With dictionaries, the process is even simpler. Let's create a new, simple dictionary. We’ll have this dictionary map letters of the alphabet to a number that specifies their position in the alphabet. And—as you know by now—we're programmers so we're going to start at 0. Let’s write letters = { 'a': 0, 'b': 1, 'c': 2 }. I’ll also add a mapping for ‘d’ and set it to the integer number 3. To do that, we use the same square bracket notation we saw earlier by writing letters['d']. We’ll also use variable assignment and write letters['d'] = 3. If I output the dictionary now, we see that a pair was added with the string 'd' as the key and the integer number 3 as the value.

 

# let's define our letter dictionary
letters = { 'a': 0, 'b': 1, 'c': 2 }

# now, let's add the letter d
letters['d'] = 3

# we have successfully added a new letter to our dictionary
# the output should be {'a': 0, 'b': 1, 'c': 2, 'd': 3}
print(letters)

 

This is how we add items to a dictionary. Having a similar notation for accessing a dictionary value as well as for creating a new pair can be nice. If you know the key exists, you can use the square brackets to get the value associated with it. If it doesn't exist, you can use the same square brackets notation and the equal sign, which we saw when we learned about variable assignment, to create a new pair.

Let's add another one by writing letters['e'] = 4. We can again output the letters dictionary and see that ‘e’ was added. By the way, you can also create pairs that map a key to a list value. For example, letters['f'] = [4,5,6] will also work. If we run this and output the dictionary, we see that the string 'f' was mapped to a list that is made of three integer numbers: 4, 5, and 6.

 

# let's add on another letter, e
letters['e'] = 4

# the output should be {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4}
print(letters)

# we can also add a list to our dictionary as a key-value pair
letters['f'] = [4,5,6]

# the output should be {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': [4, 5, 6]}
print(letters)

 

Another cool thing about this is that if we want to change an existing value, we do so using the exact same notation. Let's say we actually want to map the string 'f' to the integer number 5. In Python, we write letters['f'] = 5. When we output the letters dictionary again, we see that the last key-value pair was updated. Now the string 'f' is mapped to the integer 5, instead of the list we had previously. Because the keys in a dictionary are unique, Python is able to determine whether to create a new pair or update an existing one by using a simple rule. If a pair exists that has the given key (in our case the string 'f'), Python updates the value of that pair. If a pair does not exist that has the given key, then Python creates a brand new pair.

 

# we can easily change the value associated with a key
letters['f'] = 5

# the output should be {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5}
print(letters)

 

Practice makes perfect, so I encourage you to create your own dictionary or use the examples here. Practice adding your own pairs or updating existing ones.

But what if we want to remove a pair from the dictionary? For that, we use the del function, which is short for delete. To completely remove the pair with the key 'f', we write del(letters['f']). When we output the dictionary, we can see that the pair was removed.

 

# deleting values is as easy as adding them
del(letters['f'])

# the output should be {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4}
print(letters)

 

(By the way, you can also use del with lists. Let's create a list, call it numbers, and set it to the numbers [10,11,12,13,14,15]. If we output it, we should see all the numbers there. And if we run del(numbers[3]), Python will delete the item in the list that is located at index position 3. We know that 10 is at index 0, 11 is at index 1, 12 is at index 2, and 13 is at index 3. We expect Python will remove number 13 from our list, but let's verify that. If we output the list after we run the delete function, we see that 13 was removed.)

 

# we can also delete values in lists based on their index position
# remember, the index starts with 0, which is 10 in this list
numbers = [10,11,12,13,14,15]

# the output should be [10, 11, 12, 13, 14, 15]
print(numbers)

# let's delete the list item at position 3
# in the numbers list, this item is the integer 13
del(numbers[3])

# the output should be [10, 11, 12, 14, 15]
print(numbers)

 

Dictionary Methods

In our final section, let’s go over a few useful dictionary methods.

The first is the keys() method, which allows us to obtain a dictionary’s keys. Let's try it out with the letters dictionary we defined above. If we run letters.keys(), we get only the keys returned. In the case of this particular dictionary, Python returns a collection of single character strings, including 'a', 'b', 'c', 'd', and 'e'. Note that the keys method takes no parameters.

 

# we can easily obtain the dictionary's keys
# the output should be dict_keys(['a', 'b', 'c', 'd', 'e'])
letters.keys()

 

In a similar fashion, we can obtain a dictionary’s values. To do that we use the values method, like so: letters.values(). Python returns 0,1,2,3,4, which, if we look at the letters dictionary, are the values.

 

# we can also obtain the values
# the output should be dict_values([0, 1, 2, 3, 4])
letters.values()

 

Finally, we can also get all of the pairs in a dictionary by calling the items method. Inputting letters.items() returns the key-value pairs. We should see them surrounded by round parentheses, which is the notation for the tuple data type. We'll learn about tuples in a future lesson.

 

# we can also output the dictionary's key-value pairs as tuples
# the output should be dict_items([('a', 0), ('b', 1), ('c', 2), ('d', 3), ('e', 4)])
letters.items()

 

I want to draw your attention to one final characteristic of dictionaries. In Python, your dictionary keys don’t necessarily have to be strings, although they usually are. Other data types (though not all) are supported. For example, you can have a dictionary that maps integer numbers to letters, which is the opposite of what we did earlier. Let's create a new dictionary and call it data. We’ll make data = {1: 'a', 2: 'b'}. To access the value that corresponds to the key that is the integer number 1, we'd write data[1]. Without context, data[1] looks like we're indexing into a list. But we're not! The integer number 1 here is not an index location, but is the key that the string 'a' is mapped to. These can be potentially confusing situations. You may run into such cases—though probably not very often—so keep an eye out for them.

 

# let's create one more dictionary
data = {1: 'a', 2: 'b'}

# to access the value for key 1, we'd write 
# the output should be 'a'
data[1]

 

As a general rule, keep the data type of each variable in mind when you're reading or writing code. This will not only allow you to follow along more easily with what's happening in the program, but it'll also prevent possible logical errors or bugs.

 

That's it for dictionary methods. Like lists, dictionaries are a powerful data type. We'll encounter them often, so take some time to get familiar with them. In the beginning, the most difficult thing about programming is getting used to the syntax. That’s why it's important to practice using many simple examples, like the ones we went through together in this article. Don't try to memorize all of this information. Instead, I encourage you to come up with your own examples of more complex dictionaries. Once you’ve mastered the basics, then add pairs, delete pairs, update values in pairs, and practice other dictionary methods. Do this enough and the successful use of dictionaries in Python will start to come naturally to you.

Thanks for following along and I'll see you in the next article. Next up: the tuple data type.

Ciprian Stratulat

CTO | Software Engineer

Ciprian Stratulat

Ciprian is a software engineer and the CTO of Edlitera. As an instructor, Ciprian is a big believer in first building an intuition about a new topic, and then mastering it through guided deliberate practice.

Before Edlitera, Ciprian worked as a Software Engineer in finance, biotech, genomics and e-book publishing. Ciprian holds a degree in Computer Science from Harvard University.