How to Use Python Dictionaries

How to Use Python Dictionaries

A Comprehensive Guide on Python Dictionary

Introduction

In this article, we will cover different ways of defining a dictionary, how to access and update values of a dictionary, the dictionary’s built-in methods, and how to use dict comprehension.

We will also learn about restrictions on keys of a dictionary, membership operators, pretty-printing a dictionary, and making a shallow copy vs deep copy of a dictionary.

What is a dictionary in Python?

Python provides several useful data types built-in, Dictionary is one such data structure.

A dictionary is a collection of key: value pairs where each value is accessed using a unique key.

This is in contrast to the list where elements are accessed using their indexes.

We can think of a dictionary as a table with two columns:

image.png

Highlights:

  • A dictionary is a collection of key: value pairs where each value is accessed using a unique key.

How to define a dictionary?

We can define a dictionary in three different ways. Let's see each one of them by converting the above pictorial representation of the dictionary into a real python one.

Using curly braces {}

We can use the curly braces to define a dictionary by providing key-value pairs separated by a ':' as key: value:

harry_info = {
    "name": "Harry",
    "age": 11,
    "house": "Gryffindor",
}

print(harry_info)
print(type(harry_info))  # <class 'dict'>

Notice that a dictionary can have values of different types.

We can also create an empty dictionary using {} as: empty_dict = {}.

Using dict() function

We can create a dictionary by passing a list of tuples to the dict function:

harry_info = dict([
                   ("name", "Harry"),
                   ("age", 11),
                   ("house", "Gryffindor")
])

print(harry_info)

Using keyword arguments in dict()

We can provide keyword arguments to the dict function when all keys are string:

harry_info = dict(
    name = "Harry",
    age = 11,
    house = "Gryffindor"
)

print(harry_info)

Values in a dictionary

A dictionary can store any type of value including another dictionary. Let's change the harry_info dictionary to contain a nested dictionary house and a list of friends:

harry_info = {
    "name": "Harry",
    "age": 11,
    "house": {
      "name": "Gryffindor",
      "Animal": "Lion",
      "Element": "Fire"   
    },
    "friends": ["Ron", "Hermione"]
}

print(harry_info)

Tip 💡

When we print the above dictionary the output would not be very readable, we can use the pprint function to pretty print a dictionary:

from pprint import pprint

pprint(harry_info)

Output:

{'age': 11,
 'friends': ['Ron', 'Hermione'],
 'house': {'Animal': 'Lion', 'Element': 'Fire', 'name': 'Gryffindor'},
 'name': 'Harry'}

Restrictions on keys

There are two restrictions we need to know when defining keys:

  1. Duplicate keys are not allowed

    If we define the same key twice, the second occurrence will override the first one:

     duplicate_dict = {
         "first": 0,
         "second": 2,
         "first":1
     }
    
     print(duplicate_dict)
    

    This will print:

    {'first': 1, 'second': 2}

    and not

    {'first': 0, 'second': 2}

    {'first': 0, 'second': 2, 'first': 1}

  2. Keys must be immutable

    Keys must have a type that is immutable, which means any type whose value doesn't change once created like int, bool, str, float, etc.

    That's why we can have a tuple as a key but not a list:

     example_dict = {
         (1, 2): "Tuple",  # Okay to use
         False: "Bool",    # Okay to use
         1: "int",         # Okay to use
         [1, 2]: "list",   # raises TypeError
     }
    

    Using a list as a key raises TypeError: unhashable type: 'list' because it is a mutable object.

    Technically, a key requires a hashable value which means that Python's built-in hash() function should return a unique hash value for that object and all immutable types satisfy this condition.

Highlights:

  • We can define a dictionary using:
    • Key-value pairs in curly braces.
    • Using dict function
  • A dictionary can have any type of value.
  • Key cannot be:
    • Duplicated
    • Mutable (more precisely unhashable)

How to access values in a dictionary?

We can access a value from a dictionary by using the square brackets [].

So dict_name[key] will return the corresponding value.

Let's try to retrieve some values from the harry_info dictionary:

print(harry_info["name"])

Output: "Harry"

print(harry_info["friends"])

Output: ['Ron', 'Hermione']

What if we try to retrieve a value using a key that doesn't exist?

Let's try that too:

print(harry_info["enemies"])

Output: KeyError: 'enemies'

We got a key error which means that we can not retrieve keys that don't exist using the square bracket syntax.

Adding a new key-value pair to the dictionary

As dictionaries are mutable structures, we can add new members by assigning values to new keys using the same square bracket operator:

Syntax: dict_name[new_key] = value

harry_info["enemies"] = ["Voldemort", "Death Eaters"]

Updating existing key-value pair of a dictionary

We can also update the key's values similarly using the square brackets:

Syntax: dict_name[key] = new_value

harry_info["age"] = 17

This will update the age key from 11 to 17.

Using Membership operator with dictionaries

We can use the in and not in operators to check whether a key exists in the dictionary or not:

print('name' in harry_info)     # Output: True

print('name' not in harry_info) # Output: False

print('year' in harry_info)     # Output: False

print('year' not in harry_info) # Output: True

Get the number of key-value pairs

Use the built-in len function to get the number of key-value pairs in a dictionary:

print(len(harry_info))  # Output: 5

Highlights:

  • Access values using dict_name[key] syntax.
  • Add a new value using dict_name[new_key] = value.
  • Update a value using the same syntax as (2).
  • Use in and not in operator to check for key existence in a dictionary.
  • Use the len function to get the number of key-value pairs.

Built-in Dictionary Methods

get(key, default=None)

This is an alternative to the [] for accessing the values using a key from a dictionary. The difference is that we can provide a default value to return when a key doesn't exist instead of raising a key error.

print(harry_info.get("name"))     # Output: Harry
print(harry_info.get("year"))     # Output: None
print(harry_info.get("year", 7))  # Output: 7

items()

Returns a list of tuples containing the key-value pairs of a dictionary.

print(list(harry_info.items()))

Output:

[('name', 'Harry'), ('age', 17), ('house', {'name': 'Gryffindor', 'Animal': 'Lion', 'Element': 'Fire'}), ('friends', ['Ron', 'Hermione']), ('enemies', ['Voldemort', 'Death Eaters'])]

We can use the items method to loop through a dictionary:

for key, value in harry_info.items():
  print(key, 'is', value)

Output:

name is Harry
age is 17
house is {'name': 'Gryffindor', 'Animal': 'Lion', 'Element': 'Fire'}
friends is ['Ron', 'Hermione']
enemies is ['Voldemort', 'Death Eaters']

keys()

Returns the list of all keys of a dictionary.

print(list(harry_info.keys()))

Output: ['name', 'age', 'house', 'friends', 'enemies']

values()

Returns the list of all values of a dictionary.

print(list(harry_info.values()))

Output: ['Harry', 17, {'name': 'Gryffindor', 'Animal': 'Lion', 'Element': 'Fire'}, ['Ron', 'Hermione'], ['Voldemort', 'Death Eaters']]

pop(key[, default])

Remove the specified key and return the corresponding value.

If the key is not found, d is returned if given, otherwise KeyError is raised.

print(harry_info.pop('enemies'))    # enemies will be removed
print(harry_info.pop('invalid_key', "Invalid Key"))
print(harry_info.pop('invalid_key'))

Output:

['Voldemort', 'Death Eaters']
Invalid Key
KeyError: 'invalid_key'

popitem()

Remove and return the last (key, value) pair as a tuple, but raise KeyError if dictionary is empty.

print(harry_info.popitem())

Output: ('friends', ['Ron', 'Hermione'])

update(iterable)

Merges a dictionary with another dictionary or with an iterable of key-value pairs.

If the dictionary or iterable passed has the same key as the original dictionary then the value of that key is overridden.

When iterable is a dictionary

d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'b': 200, 'd': 4}

d1.update(d2)

print(d1)

Output: {'a': 1, 'b': 200, 'c': 3, 'd': 4}

Notice how 'b' is updated and 'd' is added.

When iterable is a list of tuples

d1 = {'a': 1, 'b': 2, 'c': 3}

d1.update([('b', 200), ('d', 4)])

print(d1)

Output: {'a': 1, 'b': 200, 'c': 3, 'd': 4}

We can also provide a keyword arguments to update and the result will be the same:

d1 = {'a': 1, 'b': 2, 'c': 3}

d1.update(b=200, d=4)

print(d1)

Output: {'a': 1, 'b': 200, 'c': 3, 'd': 4}

fromkeys(iterable, value=None)

Create a new dictionary with keys from iterable and all values set to value.

keys = ("key1", "key2", "key3")
example_dict = dict.fromkeys(keys, "default value")
print(example_dict)

Output: {'key1': 'default value', 'key2': 'default value', 'key3': 'default value'}

setdefault(key, default=None)

Return the value for key if key is in the dictionary, otherwise insert that key with a value of default and return default.

# Returns value for 'name'
print(harry_info.setdefault("name"))   
# Returns value for 'name', default is ignored
print(harry_info.setdefault("name", "Harry Potter"))
# Adds key 'last_name' and return its value 'Potter'
print(harry_info.setdefault("last_name", "Potter"))

Output:

Harry
Harry
Potter

copy()

Performs a shallow copy of the dictionary.

harry_copy = harry_info.copy()
print(harry_copy)

Shallow copy vs deep copy

With a shallow copy if the original dictionary contains mutable values they won't be copied, therefore changing the copied dictionary will change the original one.

We can use copy.deepcopy method to perform a deepcopy as shown below:

from copy import deepcopy

d = {
    'number': 1,
    'list': [1, 2]
}

d_shallow = d.copy()
d_shallow['list'].append(3)
print("shallow copy", d_shallow)
print("original dict", d)     # d is also changed

d_deep = deepcopy(d)
d_deep['list'].append(4)
print("deep copy", d_deep)
print("original dict", d)    # d is unchanged

Output:

shallow copy {'number': 1, 'list': [1, 2, 3]}
original dict {'number': 1, 'list': [1, 2, 3]}
deep copy {'number': 1, 'list': [1, 2, 3, 4]}
original dict {'number': 1, 'list': [1, 2, 3]}

clear()

Remove all items from a dictionary

harry_info.clear()
print(harry_info)

Output: {}

Highlights:

  • Dictionary provides several methods to access, update, remove, and copy key-value pairs.

Dict Comprehension

You may be familiar with list comprehensions, it is an alternative to for loop and a concise notation to perform some operations for a collection of elements.

You can also write comprehension for a dictionary using the following syntax:

example_dict = {key:value for key, value in iterable}

where the iterable is a list of key-value tuples.

d1 = dict((k, v) for k, v in enumerate("Hello", 1))
print(d1)    # {1: 'H', 2: 'e', 3: 'l', 4: 'l', 5: 'o'}
d2 = {k: v for k, v in enumerate("Bye", 1)}
print(d2)    # {1: 'B', 2: 'y', 3: 'e'}

Enumerate function returns a key: value pair using the iterable passed to it and the start value.

You can learn more about comprehensions in Python in this article: Comprehension in Python: Explained.

Highlights:

  • Use dict comprehension to perform operations on key-value pairs of a dictionary in a concise way.

Summary

  • Dictionary is a mutable data structure to store key: value pairs.
  • Define a dictionary using curly braces or dict function.
  • Access or update values of a dictionary using square brackets.
  • Dictionary provides built-in methods to add, update, remove, and copy key-value pairs.
  • Use dict comprehensions to perform operations on dict in a concise way.

Thanks for reading.

If you found this article helpful, please like and share! Feedbacks are welcome in the comments.


You may also like:

Connect with me on Twitter, GitHub, and LinkedIn.

Did you find this article valuable?

Support Yuvraj Singh Jadon by becoming a sponsor. Any amount is appreciated!