Dictionaries in Python
Dictionaries in Python
Table of Contents
Defining a Dictionary
Accessing Dictionary Values
Dictionary Keys vs. List Indices
Building a Dictionary Incrementally
Restrictions on Dictionary Keys
Restrictions on Dictionary Values
Operators and Built-in Functions
Built-in Dictionary Methods
Conclusion
List elements are accessed by their position in the list, via indexing.
Dictionary elements are accessed via keys.
Defining a Dictionary
Dictionaries are Python’s implementation of a data structure that is more
generally known as an associative array. A dictionary consists of a collection of
key-value pairs. Each key-value pair maps the key to its associated value.
d = {
<key>: <value>,
<key>: <value>,
.
.
.
<key>: <value>
}
The following defines a dictionary that maps a location to the name of its
corresponding Major League Baseball team:
>>>
>>> MLB_team = {
... 'Colorado' : 'Rockies',
... 'Boston' : 'Red Sox',
... 'Minnesota': 'Twins',
... 'Milwaukee': 'Brewers',
... 'Seattle' : 'Mariners'
... }
Dictionary Mapping Location to MLB Team
You can also construct a dictionary with the built-in dict() function. The
argument to dict()should be a sequence of key-value pairs. A list of tuples
works well for this:
d = dict([
(<key>, <value>),
(<key>, <value),
.
.
.
(<key>, <value>)
])
MLB_team can then also be defined this way:
>>>
>>> MLB_team = dict([
... ('Colorado', 'Rockies'),
... ('Boston', 'Red Sox'),
... ('Minnesota', 'Twins'),
... ('Milwaukee', 'Brewers'),
... ('Seattle', 'Mariners')
... ])
If the key values are simple strings, they can be specified as keyword
arguments. So here is yet another way to define MLB_team:
>>>
>>> MLB_team = dict(
... Colorado='Rockies',
... Boston='Red Sox',
... Minnesota='Twins',
... Milwaukee='Brewers',
... Seattle='Mariners'
... )
Once you’ve defined a dictionary, you can display its contents, the same as
you can do for a list. All three of the definitions shown above appear as
follows when displayed:
>>>
>>> type(MLB_team)
<class 'dict'>
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Twins',
'Milwaukee': 'Brewers', 'Seattle': 'Mariners'}
The entries in the dictionary display in the order they were defined. But that is
irrelevant when it comes to retrieving them. Dictionary elements are not
accessed by numerical index:
>>>
>>> MLB_team[1]
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
MLB_team[1]
KeyError: 1
>>>
>>> MLB_team['Minnesota']
'Twins'
>>> MLB_team['Colorado']
'Rockies'
If you refer to a key that is not in the dictionary, Python raises an exception:
>>>
>>> MLB_team['Toronto']
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
MLB_team['Toronto']
KeyError: 'Toronto'
Adding an entry to an existing dictionary is simply a matter of assigning a new
key and value:
>>>
>>> MLB_team['Kansas City'] = 'Royals'
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Twins',
'Milwaukee': 'Brewers', 'Seattle': 'Mariners', 'Kansas City': 'Royals'}
If you want to update an entry, you can just assign a new value to an existing
key:
>>>
>>> MLB_team['Seattle'] = 'Seahawks'
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Twins',
'Milwaukee': 'Brewers', 'Seattle': 'Seahawks', 'Kansas City': 'Royals'}
To delete an entry, use the del statement, specifying the key to delete:
>>>
>>> del MLB_team['Seattle']
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Twins',
'Milwaukee': 'Brewers', 'Kansas City': 'Royals'}
Begone, Seahawks! Thou art an NFL team.
>>>
>>> MLB_team['Toronto']
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
MLB_team['Toronto']
KeyError: 'Toronto'
>>> MLB_team[1]
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
MLB_team[1]
KeyError: 1
In fact, it’s the same error. In the latter case, [1] looks like a numerical index,
but it isn’t.
You will see later in this tutorial that an object of any immutable type can be
used as a dictionary key. Accordingly, there is no reason you can’t use
integers:
>>>
>>> d = {0: 'a', 1: 'b', 2: 'c', 3: 'd'}
>>> d
{0: 'a', 1: 'b', 2: 'c', 3: 'd'}
>>> d[0]
'a'
>>> d[2]
'c'
In the expressions MLB_team[1], d[0], and d[2], the numbers in square brackets
appear as though they might be indices. But they have nothing to do with the
order of the items in the dictionary. Python is interpreting them as dictionary
keys. If you define this same dictionary in reverse order, you still get the same
values using the same keys:
>>>
>>> d = {3: 'd', 2: 'c', 1: 'b', 0: 'a'}
>>> d
{3: 'd', 2: 'c', 1: 'b', 0: 'a'}
>>> d[0]
'a'
>>> d[2]
'c'
The syntax may look similar, but you can’t treat a dictionary like a list:
>>>
>>> type(d)
<class 'dict'>
>>> d[-1]
Traceback (most recent call last):
File "<pyshell#30>", line 1, in <module>
d[-1]
KeyError: -1
>>> d[0:2]
Traceback (most recent call last):
File "<pyshell#31>", line 1, in <module>
d[0:2]
TypeError: unhashable type: 'slice'
>>> d.append('e')
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
d.append('e')
AttributeError: 'dict' object has no attribute 'append'
Note: Although access to items in a dictionary does not depend on order,
Python does guarantee that the order of items in a dictionary is preserved.
When displayed, items will appear in the order they were defined, and
iteration through the keys will occur in that order as well. Items added to a
dictionary are added at the end. If items are deleted, the order of the
remaining items is retained.
You can only count on this preservation of order very recently. It was added as
a part of the Python language specification in version 3.7. However, it was true
as of version 3.6 as well—by happenstance as a result of the implementation
but not guaranteed by the language specification.
>>>
>>> person = {}
>>> type(person)
<class 'dict'>
>>>
>>> person
{'fname': 'Joe', 'lname': 'Fonebone', 'age': 51, 'spouse': 'Edna',
'children': ['Ralph', 'Betty', 'Joey'], 'pets': {'dog': 'Fido', 'cat':
'Sox'}}
>>> person['fname']
'Joe'
>>> person['age']
51
>>> person['children']
['Ralph', 'Betty', 'Joey']
Retrieving the values in the sublist or subdictionary requires an additional
index or key:
>>>
>>> person['children'][-1]
'Joey'
>>> person['pets']['cat']
'Sox'
This example exhibits another feature of dictionaries: the values contained in
the dictionary don’t need to be the same type. In person, some of the values
are strings, one is an integer, one is a list, and one is another dictionary.
Just as the values in a dictionary don’t need to be of the same type, the keys
don’t either:
>>>
>>> foo = {42: 'aaa', 2.78: 'bbb', True: 'ccc'}
>>> foo
{42: 'aaa', 2.78: 'bbb', True: 'ccc'}
>>> foo[42]
'aaa'
>>> foo[2.78]
'bbb'
>>> foo[True]
'ccc'
Here, one of the keys is an integer, one is a float, and one is a Boolean. It’s not
obvious how this would be useful, but you never know.
Notice how versatile Python dictionaries are. In MLB_team, the same piece of
information (the baseball team name) is kept for each of several different
geographical locations. person, on the other hand, stores varying types of data
for a single person.
You can use dictionaries for a wide range of purposes because there are so
few limitations on the keys and values that are allowed. But there are some.
Read on!
>>>
>>> foo = {42: 'aaa', 2.78: 'bbb', True: 'ccc'}
>>> foo
{42: 'aaa', 2.78: 'bbb', True: 'ccc'}
You can even use built-in objects like types and functions:
>>>
>>> d = {int: 1, float: 2, bool: 3}
>>> d
{<class 'int'>: 1, <class 'float'>: 2, <class 'bool'>: 3}
>>> d[float]
2
>>> d = {bin: 1, hex: 2, oct: 3}
>>> d[oct]
3
However, there are a couple restrictions that dictionary keys must abide by.
First, a given key can appear in a dictionary only once. Duplicate keys are not
allowed. A dictionary maps each key to a corresponding value, so it doesn’t
make sense to map a particular key more than once.
You saw above that when you assign a value to an already existing dictionary
key, it does not add the key a second time, but replaces the existing value:
>>>
>>> MLB_team = {
... 'Colorado' : 'Rockies',
... 'Boston' : 'Red Sox',
... 'Minnesota': 'Twins',
... 'Milwaukee': 'Brewers',
... 'Seattle' : 'Mariners'
... }
>>>
>>> MLB_team = {
... 'Colorado' : 'Rockies',
... 'Boston' : 'Red Sox',
... 'Minnesota': 'Timberwolves',
... 'Milwaukee': 'Brewers',
... 'Seattle' : 'Mariners',
... 'Minnesota': 'Twins'
... }
>>> MLB_team
{'Colorado': 'Rockies', 'Boston': 'Red Sox', 'Minnesota': 'Twins',
'Milwaukee': 'Brewers', 'Seattle': 'Mariners'}
Begone, Timberwolves! Thou art an NBA team. Sort of.
>>>
>>> d = {(1, 1): 'a', (1, 2): 'b', (2, 1): 'c', (2, 2): 'd'}
>>> d[(1,1)]
'a'
>>> d[(2,1)]
'c'
(Recall from the discussion on tuples that one rationale for using a tuple
instead of a list is that there are circumstances where an immutable type is
required. This is one of them.)
However, neither a list nor another dictionary can serve as a dictionary key,
because lists and dictionaries are mutable:
>>>
>>> d = {[1, 1]: 'a', [1, 2]: 'b', [2, 1]: 'c', [2, 2]: 'd'}
Traceback (most recent call last):
File "<pyshell#20>", line 1, in <module>
d = {[1, 1]: 'a', [1, 2]: 'b', [2, 1]: 'c', [2, 2]: 'd'}
TypeError: unhashable type: 'list'
Technical Note: Why does the error message say “unhashable”?
>>>
>>> hash('foo')
11132615637596761
In future tutorials, you will encounter mutable objects which are also hashable.
>>>
>>> d = {0: 'a', 1: 'a', 2: 'a', 3: 'a'}
>>> d
{0: 'a', 1: 'a', 2: 'a', 3: 'a'}
>>> d[0] == d[1] == d[2]
True
Operators and Built-in Functions
You have already become familiar with many of the operators and built-in
functions that can be used with strings, lists, and tuples. Some of these work
with dictionaries as well.
>>>
>>> MLB_team = {
... 'Colorado' : 'Rockies',
... 'Boston' : 'Red Sox',
... 'Minnesota': 'Twins',
... 'Milwaukee': 'Brewers',
... 'Seattle' : 'Mariners'
... }
>>>
>>> MLB_team['Toronto']
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
MLB_team['Toronto']
KeyError: 'Toronto'
>>>
>>> MLB_team = {
... 'Colorado' : 'Rockies',
... 'Boston' : 'Red Sox',
... 'Minnesota': 'Twins',
... 'Milwaukee': 'Brewers',
... 'Seattle' : 'Mariners'
... }
>>> len(MLB_team)
5
d.clear()
Clears a dictionary.
d.clear() empties dictionary d of all key-value pairs:
>>>
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d
{'a': 10, 'b': 20, 'c': 30}
>>> d.clear()
>>> d
{}
d.get(<key>[, <default>])
>>>
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> print(d.get('b'))
20
>>> print(d.get('z'))
None
If <key> is not found and the optional <default> argument is specified, that
value is returned instead of None:
>>>
>>> print(d.get('z', -1))
-1
d.items()
>>>
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d
{'a': 10, 'b': 20, 'c': 30}
>>> list(d.items())
[('a', 10), ('b', 20), ('c', 30)]
>>> list(d.items())[1][0]
'b'
>>> list(d.items())[1][1]
20
d.keys()
>>>
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d
{'a': 10, 'b': 20, 'c': 30}
>>> list(d.keys())
['a', 'b', 'c']
d.values()
>>>
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d
{'a': 10, 'b': 20, 'c': 30}
>>> list(d.values())
[10, 20, 30]
Any duplicate values in d will be returned as many times as they occur:
>>>
>>> d = {'a': 10, 'b': 10, 'c': 10}
>>> d
{'a': 10, 'b': 10, 'c': 10}
>>> list(d.values())
[10, 10, 10]
Technical Note: The .items(), .keys(), and .values() methods actually return
something called a view object. A dictionary view object is more or less like a
window on the keys and values. For practical purposes, you can think of these
methods as returning lists of the dictionary’s keys and values.
d.pop(<key>[, <default>])
>>>
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d.pop('b')
20
>>> d
{'a': 10, 'c': 30}
d.pop(<key>) raises a KeyError exception if <key> is not in d:
>>>
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d.pop('z')
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
d.pop('z')
KeyError: 'z'
If <key> is not in d, and the optional <default> argument is specified, then that
value is returned, and no exception is raised:
>>>
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d.pop('z', -1)
-1
>>> d
{'a': 10, 'b': 20, 'c': 30}
d.popitem()
>>>
>>> d = {'a': 10, 'b': 20, 'c': 30}
>>> d.popitem()
('c', 30)
>>> d
{'a': 10, 'b': 20}
>>> d.popitem()
('b', 20)
>>> d
{'a': 10}
If d is empty, d.popitem() raises a KeyError exception:
>>>
>>> d = {}
>>> d.popitem()
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
d.popitem()
KeyError: 'popitem(): dictionary is empty'
d.update(<obj>)
Merges a dictionary with another dictionary or with an iterable of key-value
pairs.
If <obj> is a dictionary, d.update(<obj>) merges the entries from <obj> into d.
For each key in <obj>:
If the key is not present in d, the key-value pair from <obj> is added to d.
If the key is already present in d, the corresponding value in d for that
key is updated to the value from <obj>.
>>>
>>> d1 = {'a': 10, 'b': 20, 'c': 30}
>>> d2 = {'b': 200, 'd': 400}
>>> d1.update(d2)
>>> d1
{'a': 10, 'b': 200, 'c': 30, 'd': 400}
In this example, key 'b' already exists in d1, so its value is updated to 200, the
value for that key from d2. However, there is no key 'd' in d1, so that key-value
pair is added from d2.
>>>
>>> d1 = {'a': 10, 'b': 20, 'c': 30}
>>> d1.update([('b', 200), ('d', 400)])
>>> d1
{'a': 10, 'b': 200, 'c': 30, 'd': 400}
Or the values to merge can be specified as a list of keyword arguments:
>>>
>>> d1 = {'a': 10, 'b': 20, 'c': 30}
>>> d1.update(b=200, d=400)
>>> d1
{'a': 10, 'b': 200, 'c': 30, 'd': 400}
Conclusion
In this tutorial, you covered the basic properties of the Python dictionary and
learned how to access and manipulate dictionary data.
Next you will learn about Python sets. The set is another composite data type,
but it is quite different from either a list or dictionary.