Python’s Dict Tutorial: Is a Dictionary a Data Structure?

Avatar

By squashlabs, Last Updated: October 14, 2023

Python’s Dict Tutorial: Is a Dictionary a Data Structure?

What is a Dictionary?

In Python, a dictionary is a built-in data structure that allows you to store a collection of key-value pairs. It is an unordered collection, which means that the elements in a dictionary are not stored in any particular order. Instead, they are stored based on their associated keys. Dictionaries are also known as associative arrays, hash maps, or hash tables in other programming languages.

A dictionary can be created by enclosing a comma-separated list of key-value pairs in curly braces {}. Each key-value pair is separated by a colon (:), where the key is followed by the value. Here’s an example:

my_dict = {'name': 'John', 'age': 25, 'city': 'New York'}

In this example, ‘name’, ‘age’, and ‘city’ are the keys, and ‘John’, 25, and ‘New York’ are the corresponding values.

How Does a Dictionary Work?

Under the hood, a dictionary in Python is implemented as a hash table. A hash table is a data structure that uses a hash function to map keys to their associated values. This allows for efficient insertion, deletion, and retrieval of elements based on their keys.

When you store a key-value pair in a dictionary, Python calculates the hash value of the key using the hash function. The hash value is then used as an index to store the key-value pair in an array-like structure called a hash table. This index is known as the “hash bucket”.

When you want to retrieve the value associated with a specific key, Python calculates the hash value of the key again and uses it to locate the corresponding hash bucket. If multiple keys have the same hash value (known as a hash collision), Python uses a technique called “chaining” to store them in the same hash bucket.

Key-Value Pairs in Dictionaries

In dictionaries, each key must be unique. If you try to add a new key-value pair with the same key as an existing pair, the value of the existing pair will be overwritten with the new value. However, values in a dictionary can be duplicated.

Let’s consider an example to illustrate this:

student_scores = {'Alice': 95, 'Bob': 80, 'Alice': 90}
print(student_scores)

Output:

{'Alice': 90, 'Bob': 80}

In this example, the initial score of Alice (95) is overwritten with the new score (90). It’s important to keep in mind that dictionaries are not ordered, so the order of the key-value pairs may vary when printed.

Immutable Keys in Dictionaries

In Python, dictionary keys must be immutable objects. Immutable objects are those whose state cannot be modified after they are created. This requirement is necessary because dictionaries use the hash value of the keys to store and retrieve values efficiently.

Immutable objects in Python include numbers, strings, and tuples. For example, you can use integers, floats, strings, or tuples as dictionary keys. However, you cannot use mutable objects like lists or dictionaries as keys.

Let’s see an example:

my_dict = {1: 'one', 2.5: 'two point five', ('x', 'y'): 'tuple key'}
print(my_dict)

Output:

{1: 'one', 2.5: 'two point five', ('x', 'y'): 'tuple key'}

In this example, the dictionary my_dict has integer, float, and tuple keys. The values associated with these keys are strings.

Mutable Values in Dictionaries

While dictionary keys must be immutable, the values associated with the keys can be of any type, including mutable objects such as lists or dictionaries. This allows you to store complex data structures within a dictionary.

Here’s an example that demonstrates how you can have mutable values in a dictionary:

student_data = {'name': 'John', 'grades': [80, 85, 90]}
print(student_data)

Output:

{'name': 'John', 'grades': [80, 85, 90]}

In this example, the dictionary student_data has a string value associated with the key ‘name’, and a list value associated with the key ‘grades’.

Dictionary Methods

Python provides a variety of built-in methods that you can use to manipulate dictionaries. These methods allow you to add, update, remove, and perform other operations on key-value pairs.

Let’s explore some of the commonly used dictionary methods with examples:

1. get()

The get() method returns the value associated with a specified key. If the key doesn’t exist in the dictionary, it returns a default value instead of throwing an error.

my_dict = {'name': 'John', 'age': 25, 'city': 'New York'}
print(my_dict.get('name'))
print(my_dict.get('gender', 'Unknown'))

Output:

John
Unknown

In this example, my_dict.get('name') returns the value ‘John’ associated with the key ‘name’. Since the key ‘gender’ doesn’t exist in the dictionary, my_dict.get('gender', 'Unknown') returns the default value ‘Unknown’.

2. keys()

The keys() method returns a view object that contains all the keys in the dictionary.

my_dict = {'name': 'John', 'age': 25, 'city': 'New York'}
print(my_dict.keys())

Output:

dict_keys(['name', 'age', 'city'])

In this example, my_dict.keys() returns a view object that contains the keys ‘name’, ‘age’, and ‘city’ in the dictionary my_dict.

3. values()

The values() method returns a view object that contains all the values in the dictionary.

my_dict = {'name': 'John', 'age': 25, 'city': 'New York'}
print(my_dict.values())

Output:

dict_values(['John', 25, 'New York'])

In this example, my_dict.values() returns a view object that contains the values ‘John’, 25, and ‘New York’ in the dictionary my_dict.

4. items()

The items() method returns a view object that contains all the key-value pairs in the dictionary as tuples.

my_dict = {'name': 'John', 'age': 25, 'city': 'New York'}
print(my_dict.items())

Output:

dict_items([('name', 'John'), ('age', 25), ('city', 'New York')])

In this example, my_dict.items() returns a view object that contains the key-value pairs as tuples in the dictionary my_dict.

These are just a few examples of the many methods available for dictionaries in Python. The official Python documentation provides a comprehensive list of all the dictionary methods and their usage.

A better way to build and deploy Web Apps

  Cloud Dev Environments
  Test/QA enviroments
  Staging

One-click preview environments for each branch of code.

Dictionary Comprehension

Similar to list comprehension, Python also provides a concise way to create dictionaries using dictionary comprehension. Dictionary comprehension allows you to create dictionaries by specifying both the keys and the values in a single line of code.

Here’s an example:

squares = {x: x**2 for x in range(1, 6)}
print(squares)

Output:

{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

In this example, the dictionary squares is created using dictionary comprehension. It contains the squares of numbers from 1 to 5 as key-value pairs.

You can also add conditions to filter the elements included in the dictionary comprehension. For example:

even_squares = {x: x**2 for x in range(1, 6) if x % 2 == 0}
print(even_squares)

Output:

{2: 4, 4: 16}

In this example, the dictionary even_squares is created using dictionary comprehension with a condition to include only even numbers and their squares.

Dictionary comprehension is a useful feature in Python that allows you to create dictionaries quickly and efficiently.

Nested Dictionaries

In Python, you can have dictionaries within dictionaries, known as nested dictionaries. This allows you to organize and represent complex data structures in a hierarchical manner.

Here’s an example:

student_records = {
    'Alice': {'math': 90, 'science': 85, 'english': 95},
    'Bob': {'math': 80, 'science': 90, 'english': 85}
}
print(student_records)

Output:

{
    'Alice': {'math': 90, 'science': 85, 'english': 95},
    'Bob': {'math': 80, 'science': 90, 'english': 85}
}

In this example, student_records is a dictionary that contains nested dictionaries. Each nested dictionary represents the scores of a student in different subjects.

You can access the values in nested dictionaries by using multiple square brackets. For example:

print(student_records['Alice']['math'])

Output:

90

In this example, student_records['Alice']['math'] retrieves the math score of Alice from the nested dictionaries.

Nested dictionaries are a useful way to represent and work with hierarchical data structures in Python.

Dictionary Operations

Python provides a set of operations that you can perform on dictionaries, such as creating a dictionary, accessing elements, updating elements, removing elements, copying dictionaries, iterating through dictionaries, and more. Let’s explore some of these operations with examples.

Creating a Dictionary

You can create a dictionary in Python by enclosing a comma-separated list of key-value pairs in curly braces {}. Each key-value pair is separated by a colon (:), where the key is followed by the value.

Here’s an example:

student_scores = {'Alice': 95, 'Bob': 80, 'Charlie': 90}
print(student_scores)

Output:

{'Alice': 95, 'Bob': 80, 'Charlie': 90}

In this example, the dictionary student_scores is created with three key-value pairs representing the scores of three students.

Accessing Dictionary Elements

You can access the value associated with a specific key in a dictionary by using square brackets [] and specifying the key.

Here’s an example:

student_scores = {'Alice': 95, 'Bob': 80, 'Charlie': 90}
print(student_scores['Alice'])

Output:

95

In this example, student_scores['Alice'] retrieves the value 95 associated with the key ‘Alice’ from the dictionary student_scores.

Updating Dictionary Elements

You can update the value associated with a specific key in a dictionary by assigning a new value to that key.

Here’s an example:

student_scores = {'Alice': 95, 'Bob': 80, 'Charlie': 90}
student_scores['Bob'] = 85
print(student_scores)

Output:

{'Alice': 95, 'Bob': 85, 'Charlie': 90}

In this example, student_scores['Bob'] is updated from 80 to 85.

Removing Dictionary Elements

You can remove a key-value pair from a dictionary using the del keyword followed by the key.

Here’s an example:

student_scores = {'Alice': 95, 'Bob': 80, 'Charlie': 90}
del student_scores['Bob']
print(student_scores)

Output:

{'Alice': 95, 'Charlie': 90}

In this example, the key-value pair with the key ‘Bob’ is removed from the dictionary student_scores.

Copying a Dictionary

You can create a copy of a dictionary using the copy() method or by using the built-in dict() function.

Here’s an example using the copy() method:

student_scores = {'Alice': 95, 'Bob': 80, 'Charlie': 90}
student_scores_copy = student_scores.copy()
print(student_scores_copy)

Output:

{'Alice': 95, 'Bob': 80, 'Charlie': 90}

In this example, student_scores.copy() creates a copy of the dictionary student_scores.

Iterating Through a Dictionary

You can iterate through a dictionary using a for loop and access both the keys and values using the items() method.

Here’s an example:

student_scores = {'Alice': 95, 'Bob': 80, 'Charlie': 90}
for name, score in student_scores.items():
    print(name, score)

Output:

Alice 95
Bob 80
Charlie 90

In this example, student_scores.items() returns a view object that contains the key-value pairs in the dictionary student_scores. The for loop iterates over each key-value pair, and the variables name and score are used to unpack the key and value.

Checking if a Key Exists in a Dictionary

You can check if a specific key exists in a dictionary using the in keyword.

Here’s an example:

student_scores = {'Alice': 95, 'Bob': 80, 'Charlie': 90}
print('Alice' in student_scores)
print('David' in student_scores)

Output:

True
False

In this example, 'Alice' in student_scores returns True because the key ‘Alice’ exists in the dictionary student_scores. 'David' in student_scores returns False because the key ‘David’ does not exist in the dictionary.

These are just a few examples of the operations you can perform on dictionaries in Python. Dictionaries provide a flexible and efficient way to store and manipulate data in various applications.

Dictionary Size and Memory Usage

The size of a dictionary in Python depends on the number of key-value pairs it contains and the size of the keys and values themselves. The memory usage of a dictionary is influenced by the number of items it holds and the memory requirements of the objects used as keys and values.

To determine the size of a dictionary, you can use the sys.getsizeof() function from the sys module.

Here’s an example:

import sys

my_dict = {'name': 'John', 'age': 25, 'city': 'New York'}
print(sys.getsizeof(my_dict))

Output:

240

In this example, sys.getsizeof(my_dict) returns the size of the dictionary my_dict in bytes. The actual size may vary depending on the Python implementation and the platform you are using.

The size of a dictionary increases as you add more key-value pairs to it. However, the size does not increase linearly with the number of items in the dictionary. The underlying hash table structure used by dictionaries allows for efficient storage and retrieval of items, even for large dictionaries.

Common Dictionary Operations

Python dictionaries provide a wide range of operations that you can use to manipulate and work with dictionary objects. Here are some common dictionary operations:

Sorting a Dictionary

Dictionaries in Python are inherently unordered, which means that the order of elements is not guaranteed. However, you can sort a dictionary based on its keys or values using the sorted() function.

Here’s an example of sorting a dictionary by keys:

my_dict = {'name': 'John', 'age': 25, 'city': 'New York'}
sorted_dict = {key: my_dict[key] for key in sorted(my_dict)}
print(sorted_dict)

Output:

{'age': 25, 'city': 'New York', 'name': 'John'}

In this example, sorted(my_dict) returns a sorted list of keys from the dictionary my_dict. The dictionary comprehension {key: my_dict[key] for key in sorted(my_dict)} creates a new dictionary with the sorted keys and their corresponding values.

You can also sort a dictionary based on its values by using the sorted() function with a lambda function as the key parameter.

Merging Dictionaries

You can merge two or more dictionaries in Python using the update() method or the ** operator.

Here’s an example using the update() method:

dict1 = {'name': 'John', 'age': 25}
dict2 = {'city': 'New York', 'country': 'USA'}
dict1.update(dict2)
print(dict1)

Output:

{'name': 'John', 'age': 25, 'city': 'New York', 'country': 'USA'}

In this example, dict1.update(dict2) merges the key-value pairs from dict2 into dict1.

You can also merge dictionaries using the ** operator, which unpacks the key-value pairs of a dictionary into another dictionary.

Here’s an example using the ** operator:

dict1 = {'name': 'John', 'age': 25}
dict2 = {'city': 'New York', 'country': 'USA'}
merged_dict = {<strong>dict1, </strong>dict2}
print(merged_dict)

Output:

{'name': 'John', 'age': 25, 'city': 'New York', 'country': 'USA'}

In this example, {<strong>dict1, </strong>dict2} combines the key-value pairs from dict1 and dict2 into a new dictionary.

Clearing a Dictionary

You can remove all the key-value pairs from a dictionary using the clear() method.

Here’s an example:

my_dict = {'name': 'John', 'age': 25, 'city': 'New York'}
my_dict.clear()
print(my_dict)

Output:

{}

In this example, my_dict.clear() removes all the key-value pairs from the dictionary my_dict, resulting in an empty dictionary.

Dictionary View Objects

Python provides three view objects for dictionaries: keys(), values(), and items(). These view objects provide dynamic views of the dictionary’s keys, values, and key-value pairs, respectively. They allow you to access and iterate over the dictionary’s contents without creating new lists or dictionaries.

Here’s an example:

my_dict = {'name': 'John', 'age': 25, 'city': 'New York'}
keys_view = my_dict.keys()
values_view = my_dict.values()
items_view = my_dict.items()

print(keys_view)
print(values_view)
print(items_view)

my_dict['country'] = 'USA'

print(keys_view)
print(values_view)
print(items_view)

Output:

dict_keys(['name', 'age', 'city'])
dict_values(['John', 25, 'New York'])
dict_items([('name', 'John'), ('age', 25), ('city', 'New York')])
dict_keys(['name', 'age', 'city', 'country'])
dict_values(['John', 25, 'New York', 'USA'])
dict_items([('name', 'John'), ('age', 25), ('city', 'New York'), ('country', 'USA')])

In this example, my_dict.keys(), my_dict.values(), and my_dict.items() return view objects that reflect the current state of the dictionary my_dict. Any changes made to the dictionary are immediately reflected in the view objects.

Dictionary vs List Performance

Dictionaries and lists are both widely used data structures in Python, but they have different performance characteristics. Understanding these differences can help you choose the appropriate data structure for your specific use case.

Dictionaries provide fast access to values based on their keys. The time complexity for dictionary operations like accessing, inserting, and deleting elements is O(1) on average. This means that the time taken to perform these operations does not depend on the size of the dictionary.

On the other hand, lists provide fast access to elements based on their index. The time complexity for list operations like accessing elements by index, inserting elements at a specific position, and deleting elements is O(1) for the best and average case when the index is known. However, finding the index of an element or removing elements from an arbitrary position in the list has a time complexity of O(n), where n is the size of the list.

In terms of memory usage, dictionaries generally require more memory than lists because they need to store both the keys and values. The memory usage of dictionaries increases with the number of key-value pairs and the size of the keys and values. Lists, on the other hand, only need to store the elements themselves.

Additional Resources

Python Dictionaries

More Articles from the Python Tutorial: From Basics to Advanced Concepts series: