Di

Dicts in Python

36 exercises

About Dicts

A dictionary (dict) in Python is a data structure that associates hashable keys to values and is known in other programming languages as a resizable hash table, hashmap, or associative array. Dictionaries are Python's only built-in mapping type.

Keys must be hashable and unique across the dictionary. Key types can include numbers, str, or tuples (of immutable values). They cannot contain mutable data structures such as lists, dicts, or sets. As of Python 3.7, dict key order is guaranteed to be the order in which entries are inserted.

values can be of any data type or structure. Values can also nest arbitrarily, so they can include lists-of-lists, sub-dictionaries, and other custom or compound data structures.

Given a key, dictionaries can retrieve a value in (on average) constant time (independent of the number of entries). Compared to searching for a value within a list or array (without knowing the index position), a dict uses significantly more memory, but has very rapid retrieval.

Dictionaries are especially useful in scenarios where the collection of items is large and must be accessed and updated frequently.

Dictionary Construction

Dictionaries can be created in many different ways, including:

  • Using the fromkeys() classmethod
  • Creating dictionary comprehensions
  • Merging two dictionaries via unpacking (**)
  • Merging dictionaries via the | (update) operator
  • Using a loop to iteratively add entries to a previously created empty dict.

The two most straightforward methods are the dictionary constructor and the dictionary literal.

The Dictionary Constructor

dict() (the constructor for the dict class) can be used with any iterable of key, value pairs. It can also be called with a series of <name>=<value> arguments:

# Passing a list of key,value tuples.
>>> wombat = dict([('name', 'Wombat'),('speed', 23),
                   ('land_animal', True)])
{'name': 'Wombat', 'speed': 23, 'land_animal': True}


# Using key=value arguments.
>>> bear = dict(name="Black Bear", speed=40, land_animal=True)
{'name': 'Black Bear', 'speed': 40, 'land_animal': True}

The documentation on dicts outlines additional variations and options in constructor use.

Dictionary Literals

A dictionary can also be directly entered as a dictionary literal, using curly brackets ({}) enclosing key : value pairs. Entries that are enclosed in the {} can also appear on separate lines:

>>> whale = {"name": "Blue Whale", 
             "speed": 35, 
             "land_animal": False}
{'name': 'Blue Whale', 'speed': 35, 'land_animal': False}

>>> wombat = {'name': 'Wombat',
              'speed': 23,
              'land_animal': True,
              'color': 'Brindle'}

>>> wombat
{'name': 'Wombat', 'speed': 23, 'land_animal': True, 'color': 'Brindle'}

Nested Dictionaries

Dictionaries can be arbitrarily nested:

animals = {
            "Real" : {
                "Winged" : {
                            "Sparrow" : {'name': 'sparrow','speed': 12, 'land_animal': True},
                            "Kestrel" : {'name': 'kestrel', 'speed': 15, 'land_animal': True}
                           },
                "Legged" : {
                            "Wombat" : {'name': 'Wombat', 'speed': 23, 'land_animal': True},
                            "Black Bear": {'name': 'Black Bear', 'speed': 40, 'land_animal': True},
                            "Polecat" : {'name': 'Polecat', 'speed': 15, 'land_animal': True}
                           },
                "Other" :  {
                            "Whale" : {'name': 'Blue Whale', 'speed': 35, 'land_animal': False},
                            "Orca" : {'name': 'Orca', 'speed': 45, 'land_animal': False},
                            "Snake" : {'name': 'Python', 'speed': 25, 'land_animal': True}
                            }
                },
        
        "Imaginary": {
                "Winged" : {
                            "Dragon" : {'name': 'Fire Dragon','speed': 100, 'land_animal': True},
                            "Phoenix" : {'name': 'Phoenix', 'speed': 1500, 'land_animal': True}
                            },
                "Legged" : {
                            "Sphinx" : {'name': 'Sphinx','speed': 10, 'land_animal': True},
                            "Minotaur" : {'name': 'Minotaur', 'speed': 5, 'land_animal': True}
                            },
                "Other" :  {}
                }
       }

Accessing Values in a dict

You can access a value in a dictionary using a key in square brackets. If a key does not exist, a KeyError is thrown:

>>> bear["speed"]
40

>>> bear["color"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'color'

Accessing an entry via the get(<key>, <default value>) method can avoid the KeyError:

>>> bear.get("color", 'not found')
'not found'

Accessing Nested Dictionary Entries

To access entries in nested dictionaries, use successive brackets. If a given key is missing, the usual KeyError will be thrown:

# Using the animals nested dictionary.
>>> animals["Real"]["winged"]["Kestrel"]["speed"]
15

>>> animals["Imaginary"]["winged"]["Kestrel"]["speed"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'Kestrel'

To avoid the KeyError, .get() can be used, but the calls to .get() must be chained:

# Using the animals nested dictionary.
# Note the use of parenthesis to enable placing the 
# .get() calls on separate lines.
>>> (animals.get("Imaginary", {})
            .get("Legged", {})
            .get("Sphinx", {})
            .get("Color", "I have no idea!"))
'I have no idea!'

Changing or Adding Dictionary Values

You can change an entry value by assigning to its key:

# Assigning the value "Grizzly Bear" to the name key.
>>> bear["name"] = "Grizzly Bear"
{'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True}

>>> whale["speed"] = 25
{'name': 'Blue Whale', 'speed': 25, 'land_animal': False}

New key:value pairs can be added in the same fashion:

# Adding an new "color" key with a new "tawney" value.
>>> bear["color"] = 'tawney'
{'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True, 'color': 'tawney'}

>>> whale["blowholes"] = 1
{'name': 'Blue Whale', 'speed': 25, 'land_animal': False, 'blowholes': 1}

Removing (Pop-ing and del) Dictionary Entries

You can use the .pop(<key>) method to delete a dictionary entry. .pop() removes the (key, value) pair and returns the value for use. Like .get(), .pop(<key>) accepts second argument (dict.pop(<key>, <default value>)) that will be returned if the key is not found. This prevents a KeyError being raised:

# Using .pop() removes both the key and value, returning the value.
>>> bear.pop("name")
'Grizzly Bear'


# The "name" key is now removed from the dictionary.
# Attempting .pop() a second time will throw a KeyError.
>>> bear.pop("name")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'name'


# Using a default argument with .pop() will 
# prevent a KeyError from a missing key.
>>> bear.pop("name", "Unknown")
'Unknown'

You can also use the del statement to remove a single or multiple entries. A KeError is raised if the entry to be removed is not found in the dictionary:

>>> wombat = {'name': 'Wombat',
              'speed': 23,
              'land_animal': True,
              'color': 'Brindle',
              'talent': 'Singing',
              'size': 'small'}

# Remove a single entry from the dictionary.
>>> del wombat["color"]
>>> wombat
{'name': 'Wombat', 'speed': 23, 'land_animal': True, 'talent': 'Singing', 'size': 'small'}


# Remove multiple entries from the dictionary.
>>> del wombat["talent"], wombat["size"]
>>> wombat
{'name': 'Wombat', 'speed': 23, 'land_animal': True}


# Attempting a deletion of a non-existent key raises a KeyError
>>> del wombat["number_of_legs"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'number_of_legs'

Looping Through/Iterating over a Dictionary

Looping through a dictionary using for item in dict or while item will iterate over the keys by default. You can access values within the same loop by using square brackets:

>>> for key in bear:
>>>     print((key, bear[key])) #this prints a tuple of (key, value)
('name', 'Black Bear')
('speed', 40)
('land_animal', True)

You can also use the .items() method, which returns (key, value) tuples:

# dict.items() forms (key, value tuples) that can be 
# unpacked and iterated over.
>>> for key, value in whale.items():
>>>     print(key, ":", value)
name : Blue Whale
speed : 25
land_animal : False
blowholes : 1

Likewise, .keys() will return the keys and .values() will return the values.

For a detailed explanation of dictionaries in Python, the official documentation is an excellent starting place, or you can also check out the W3-Schools tutorial.

Extending Dictionary Functionality: The Collections Module

The collections module adds specialized functionality to Python's standard collection-based datatypes (dictionary, set, list, tuple). Three of the most useful dictionary-based classes are:

  • Counter automatically counts items and returns them in a dict with the items as keys and their counts as values.
  • OrderedDict, has methods specialized for arranging the order of dictionary entries.
  • defaultdict uses a factory method to set a default value if a key is not found when trying to retrieve or assign to a dictionary entry.
Edit via GitHub The link opens in a new window or tab

Learn Dicts

Practicing is locked

Unlock 4 more exercises to practice Dicts