The Python dictionary is one of the language’s most powerful data types. In other programming languages and computer science in general, dictionaries are also known as associative arrays. They allow you to associate keys to values.
Creating a Python Dictionary
Let’s look at how we can create and use a Python dictionary in the Python REPL:
>>> phone_numbers = { 'Jack': '070-02222748',
'Pete': '010-2488634' }
>>> my_empty_dict = { }
>>> phone_numbers['Jack']
'070-02222748'
The first dictionary associates keys (names like Jack and Pete) with values (their phone numbers). The second dictionary is an empty one.
Now that you’ve seen how to initialize a dictionary, let’s see how we can add and remove entries to an already existing one:
>>> phone_numbers['Eric'] = '06-10101010'
>>> del(phone_numbers['Jack'])
>>> phone_numbers
{'Pete': '010-2488634', 'Eric': '06-10101010'}
Valid dictionary values
You can put anything in a dictionary. You’re not limited to numbers or strings. In fact, you can put dictionaries and lists inside your dictionary and access the nested values in a very natural way:
>>> a = { 'sub_dict': { 'b': True },
'mylist': [100, 200, 300] }
>>> a['sub_dict']['b']
True
>>> a['mylist'][0]
100
Python’s JSON decoding and encoding library uses this feature of Python when parsing more complex JSON documents. It creates nested trees of lists, dictionaries, and other valid data types.
Valid dictionary keys
If you want, you can go pretty crazy on your dictionary keys too. The only requirement is that the key is of an immutable data type. Mutable types like lists, dictionaries, and sets won’t work.
Besides this limitation, you can use all data types as a dictionary key, including native types like float and int. Although completely useless for most, I’ll demonstrate anyway:
>>> crazy_dictionary = { int: 1, float: 2, dict: 3 }
>>> crazy_dictionary[dict]
3
A more likely use-case is the use of numbers as keys. For example, consider this registration of runners in a marathon:
>>> runners = { 1000: 'Jack', 1001: 'Eric',
1002: 'Lisa' }
>>> runners[1001]
'Eric'
More ways to create a Python dictionary
There are more advanced ways to initialize a dictionary that might come in handy, depending on your data source.
Using the dict() constructor
The dict() function builds a dictionary from a sequence or list of key-value pairs:
>>> dict([ ('Jack', '070-02222748'),
('Pete', '010-2488634'),
('Eric', '06-10101010') ])
{'Jack': '070-02222748', 'Pete': '010-2488634', 'Eric': '06-10101010'}
Dictionary Comprehensions
Analogous to list comprehensions, you can also use dictionary comprehensions to create a new dictionary.
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
For a more details explanation of comprehensions, please read our article on list comprehensions.
Using dict.fromkeys
The dict.fromkeys(keys, value) method creates a new dictionary, based on the list of keys supplied to it. The value of all elements will be set to the supplied value, or None by default, if you don’t supply a value.
So the following code:
>>> names = ('Eric', 'Martha', 'Ellen')
>>> phone_numbers = dict.fromkeys(names, None)
>>> phone_numbers
{'Ellen': None, 'Eric': None, 'Martha': None}
Parse a JSON dictionary
As explained in the section about working with JSON, you can also decode JSON data into a dictionary like this:
>>> import json
>>> jsonstring = '{ "name": "erik", "age": 38,
"married": true}'
>>> json.loads(jsonstring)
{'name': 'erik', 'age': 38, 'married': True}
Using Python dictionaries
Dictionary view objects
Some built-in dictionary methods return a view object, offering a window on your dictionary’s key and values. Values in a view object chance as the content of the dictionary changes. This is best illustrated with an example:
phone_numbers = { 'Jack': '070-02222748',
'Pete': '010-2488634',
'Eric': '06-10101010' }
names = phone_numbers.keys()
phone_numbers['Linda'] = 9876
print(names)
The output of this code is dict_keys(['Jack', 'Pete', 'Eric', 'Linda']). As you can see, Linda is part of the list too, even though she got added after creating the names view object.
Access and delete a single key/value pair
We’ve already seen how to access and delete a single key/value-pair:
>>> phone_numbers['Eric'] = '06-10101010'
>>> del(phone_numbers['Jack'])
To overwrite an entry, simply assign a new value to it. You don’t need to del() it first.
If the requested key does not exist, an exception of type KeyError is thrown:
>>> phone_numbers['lisa']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'lisa'
If you know data can be missing, e.g., when parsing input from the outside world, make sure to surround your code with a try ... except KeyError.
Default values
Another way to retrieve a single value from a dictionary, is using the get-method. The advantage? It returns a default value, None, if the key was not found. You can specify your own default value too.
With the get-method, you don’t have to surround the operation with a try… except. It’s ideal when working with configuration data that is parsed from YAML or JSON files, where your software offers defaults for unset configuration items.
An example:
>>> config = { 'host': 'example.org' }
>>> config.get('port', 80)
80
>>> config.get('schema')
None
Get all the keys from a Python dictionary
There are two easy ways to get all the keys from a dictionary:
>>> phone_numbers = { 'Jack': '070-02222748',
'Pete': '010-2488634',
'Eric': '06-10101010' }
>>> list(phone_numbers)
['Jack', 'Pete', 'Eric']
>>> sorted(phone_numbers)
['Eric', 'Jack', 'Pete']
list() returns all the keys in insertion order, while sorted() returns all the keys sorted alphabetically.
There’s also the dict.keys() method, which returns a view object containing a list of all the dictionary keys. The advantage of this object is that it stays in sync with the dictionary. It’s perfect for looping over all the keys, but you still might opt for the list or sorted methods though, because those return a native list that you can manipulate as well.
Check if a key exists in a Python dictionary
You can check if a key exists inside a dictionary with the in and not in keywords:
>>> 'Jack' in phone_numbers
True
>>> 'Jack' not in phone_numbers
False
Getting the length of a Python dictionary
The len() returns the number of key/value pairs in a dictionary:
>>> phone_numbers = { 'Jack': '070-02222748',
'Pete': '010-2488634',
'Eric': '06-10101010' }'06-10101010' }
>>> len(phone_numbers)
3
Looping through a Python dictionary
The items() method of a dictionary returns an iterable view object, offering both the keys and values, as can be seen below. You can loop through this object with a simple for-loop:
>>> phone_numbers.items()
dict_items([('Jack', '070-02222748'),
('Pete', '010-2488634'),
('Eric', '06-10101010')])
>>> for name, phonenr in phone_numbers.items():
... print(name, ":", phonenr)
...
Jack : 070-02222748
Pete : 010-2488634
Eric : 06-10101010
Alternatively, you can use the keys() and values() methods to loop through just the keys or values. Both functions return an iterable view object.
Merging dictionaries
Since Python 3.5, you can merge two dictionaries easily:
dict1 = { 'a': 1, 'b': 2 }
dict2 = { 'b': 3, 'c': 4 }
merged = { **dict1, **dict2 }
print (merged)
# {'a': 1, 'b': 3, 'c': 4}
If you’re running Python 3.9, it gets even better because you can use the newly introduced merging operator for dictionaries:
merged = dict1 | dict2
Comparing Python dictionaries
If you need to compare two dictionaries, you can simply use a comparison operator like this:
>>> first_dict = { 'a': 1, 'b': 2, 'c': 'a string' }
>>> second_dict = { 'a': 1, 'b': 2, 'c': 'a string' }
>>> first_dict == second_dict
True
This looks and sounds trivial, but it’s not! A dictionary can contain objects of any type, after all! Consequently, Python has to walk through all the keys and values and individually compare them.
You might wonder if a dictionary with the same keys and values, but inserted in another order, are the same too. Let’s check this:
>>> first_dict = { 'a': 1, 'b': 2, 'c': 'a string' }
>>> second_dict = { 'b': 2, 'a': 1, 'c': 'a string' }
>>> first_dict == second_dict
True
They are the same to Python, despite having a different order.
Good to know: the order of dictionaries is guaranteed to be insertion order since Python 3.7. This means that the order of the dictionary is determined by the order in which you insert items.
Built-in Python dictionary methods
Each dictionary inherits a number of handy built-in functions, as listed in the following table:
| Method | What is does | Example |
|---|---|---|
clear() | Remove all key/value pairs (empty the dictionary) | phone_numbers.clear() |
get(key) | Get a single item with given key, with optional default value | phone_numbers.get('Martha', 'Unknown person') |
items() | Returns a view object containing key-value pairs from the dictionary | phone_numbers.items() |
keys() | Returns a view object with a list of all keys from the dictionary | phone_numbers.keys() |
values() | Returns a view_object with a list of all values from the dictionary | phone_numbers.values() |
pop(key, default_value) | Returns and removes the element with the specified key | phone_numbers.pop('Martha') |
popitem() | Returns and removes the last inserted item (Python 3.7+) or a random item | phone_numbers.popitem() |
setdefault(key, value) | Returns the value of specified key. If the key does not exist, it’s inserted with the given value | phone_numbers.setdefault('John Doe', 1234) |
update(iterable) | Add all pairs from given iterable, e.g. a dictionary | phone_numbers.update({"Alina": 1234, "Alice", 2345}) |
