Apify is all about making the web more programmable. Our SDK for Python is a great toolkit to help simplify the process of making scrapers to collect web data. This tutorial aims to give you a solid understanding of Python dictionaries for storing data.
What is a Python dictionary?
Python has a variety of built-in data structures that can store different types of data. One such data structure is the Python dictionary, which can store data in the form of key:value
pairs and allows for quick access to values associated with keys. You can think of it like a regular dictionary, where words are keys and their definitions are values.
In some other languages, the Python dictionary is called a hashtable because its keys are hashable. Python dictionaries are dynamic and mutable, which means that their data can be changed.
What are dictionaries used for in Python?
Python dictionaries are used to store data in key-value pairs, where each key is unique within a dictionary, while values may not be. The values of a dictionary can be of any type, but the keys must be of an immutable data type, such as strings, numbers, or tuples. This is because the Python dictionary is implemented internally as a hash table. So, if you hash a mutable object, then change it and hash it again, you will get a different hash.
Python dictionaries are optimized for fast lookups, making them more efficient than lists for this purpose.
In Python, the average time complexity of a dictionary key lookup is O(1) because dictionaries are implemented as hash tables, and keys are hashable. On the other hand, the time complexity of a lookup in a list is O(n) on average.
Using a Python dictionary makes the most sense under the following conditions:
If you want to store data and objects using names rather than just index numbers or positions. Use a list if you want to store elements so that you can retrieve them by their index number.
If you need to look up data and objects by names quickly. Dictionaries are optimized for constant-time lookups.
If you need to store data efficiently and flexibly. Dictionaries store unique keys, so if youve got a lot of duplicate data, dictionaries will only store unique data.
How to use dictionaries in Python
A dictionary is a group of key-value pairs. Using a dictionary in Python means working with the key-value pairs and performing various operations, such as retrieving data, deleting data, and inserting data.
What is a key-value pair?
A key-value pair is a combination of two elements: a key and a value. The key in a key-value pair must be immutable, meaning that it cannot be changed. Examples of immutable keys include numbers, strings, and tuples. Values in key-value pairs can be any type of data, including numbers, lists, strings, tuples, and even dictionaries.
The values can repeat, but the keys must remain unique. You cannot assign multiple values to the same key. However, you can assign a list of values as a single value.
How to create a dictionary?
To create a dictionary in Python, you can use curly braces {}
to enclose a sequence of items separated by commas. Each item consists of a key and a value. There are two primary methods for defining a dictionary: using a literal (curly braces) or built-in function (dict()).
First, lets create an empty dictionary and then fill it with some items.
test_dict = {}
Let's fill the dictionary with some data. Suppose weve got integer keys and string values.
test_dict = {1: "apify", 2: "crawlee"}print(test_dict)
It is not necessary that all keys be of the same type.
test_dict = {1: [2, 3, 4], "product": "crawlee"}print(test_dict) # {1: 'apify', 2: 'crawlee'}
Alternatively, you can create a dictionary by explicitly calling the Python dict()
constructor. Remember, the main usage of the built-in dict()
function is to convert between different data types.
test_dict = dict({1: "apify", 2: "crawlee"})print(test_dict) # {1: 'apify', 2: 'crawlee'}
The dictionary can be created by simply passing the key and value to the dict()
constructor, as shown below.
test_dict = dict(company="apify", product="crawlee")print(test_dict) # {'company': 'apify', 'product': 'crawlee'}
A dictionary can also be created by passing a list of tuples to the dict()
constructor.
test_dict = dict([(1, [2, 3, 4]), ("product", "apify")])print(test_dict) # {1: [2, 3, 4], 'product': 'apify'}
You can create a dictionary inside another dictionary.
nested_dict = { "product1": {"name": "Crawlee", "year": 2019}, "product2": {"name": "Actors", "year": 2022},}print(nested_dict) # {'product1': {'name': 'Crawlee', 'year': 2019}, 'product2': {'name': 'Actors', 'year': 2022}}
As discussed earlier, each key in the dictionary should be unique. The last assignment of the key overwrites the previous ones.
test_dict = {1: "apify", 1: "crawlee", 1: "proxy"}print(test_dict) # {1: 'proxy'}
In Python dictionaries, keys should be hashable (they should be immutable). Thus, mutable data types like lists aren't allowed. Let's try to hash() different data types and see what happens:
# Hashing of an integerprint(hash(1))# Hashing of a floatprint(hash(1.2))# Hashing of a stringprint(hash("apify"))# Hashing of a tupleprint(hash((1, 2)))# Hashing of a list# Lists are not hashable, so this will raise a TypeErrorprint(f"Hash of list [1, 2, 3]: {hash([1, 2, 3])}")
Heres the code result:
Example of a code result
Integers, floats, strings, and tuples are hashable data types, whereas lists are unhashable data types.
Accessing values using keys
To access the value from a Python dictionary using a key, you can use the square bracket notation or the get()
method.
To access the value using square bracket notation, place the key inside the square brackets.
test_dict[key]
In the following code, we access the values using these keys: "name" and "products.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "products": ["crawlee", "actors", "proxy"], "active": True,}print(company["name"]) # apifyprint(company["products"]) # ['crawlee', 'actors', 'proxy']
You can also use the get()
method to access the dictionary elements. Pass the name of the key as the argument to the method.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "products": ["crawlee", "actors", "proxy"], "active": True,}print(company.get("name")) # web scraping
Now, what if you're searching for the key and the key does not exist in the dictionary? If you use the square bracket notation, the program will throw a KeyError
. However, if you use the get()
method, youll get None
by default, and you can also set the default return value by passing the default values as the second argument. The following examples return "Key not found!" if the key doesn't exist.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "products": ["crawlee", "actors", "proxy"], "active": True,}print(company.get("founder")) # Noneprint(company.get("founder", "Key not found!")) # Key not found!
How to modify dictionaries
Python dictionaries are mutable, which means you can modify the dictionary items. You can add, update, or remove key-value pairs. Here are some basic operations to modify dictionaries.
Adding and updating key-value pairs
There are various ways to add new elements to a dictionary. A common way is to add a new key and assign a value to it using the =
operator.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "products": ["crawlee", "actors", "proxy"], "active": True,}company["repositories"] = 112print(company)
Heres the code result:
New key and value in code result
New key-value pairs have been added successfully.
You can add multiple values to a single key using the =
operator.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "active": True,}company["products"] = "crawlee", "actors", "proxy"print(company)
Heres the code output:
Code output with multiple values
New values have been added in the form of a tuple.
If you would like to add a key without a value, you can put None
instead of the value.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "active": True,}company["price"] = Noneprint(company)
Heres the code result:
Example of code result without a value
You can add multiple key-value pairs to an existing dictionary. This is achieved by using the update()
method. If the key is already present in the dictionary, it gets overwritten with the new value. This is the most popular method for adding key-value pairs to the Python dictionary.
Heres the code result:
Code result with multiple key-value pairs
One last method involves using the Merge (|
) and Update (|=
) operators. They were introduced in Python 3.9. The merge (|
) operator creates a new dictionary with the keys and values from both of the given dictionaries. You can then assign this newly created dictionary to a new variable.
The Update (|=
) operator adds the key-value pairs of the second dictionary to the first dictionary.
company = {"name": "apify"}new_dict = {"year": 2015, "solution": "web scraping"}# Merge Operatorresult = company | new_dictprint(result)# Update Operatorcompany |= new_dictprint(company)
Here's the code result in the Python (3.9+) interpreter:
Example of code result in the Python 3.9+ interpreter
Removing key-value pairs
The removal of key-value pairs can be done in several ways, which well discuss one by one.
The del
keyword can be used to delete key-value pairs from the dictionary. Just pass the key of the key-value pair that you want to delete.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "active": True,}del company["year"]print(company) # {"name": "apify", "solution": "web scraping", "active": True}
The "year" entry has been deleted from the Python dictionary.
Another way is to use the pop()
method to delete the key-value pair. The main difference between Pop and Del is pop
will return the popped item, whereas del
will not.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "active": True,}popped_item = company.pop("year")print(popped_item) # 2015print(company) # {'name': 'apify', 'solution': 'web scraping', 'active': True}
If you don't pass the key name, the popitem()
method removes the last item inserted into the dictionary.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "active": True,}company.popitem()print(company) # {'name': 'apify', 'year': 2015, 'solution': 'web scraping'}
Clearing a dictionary
If you want to delete the entire dictionary, it would be difficult to use the above methods on every single key to delete all the items. Instead, you can use the del
keyword to delete the entire dictionary.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "active": True,}del companyprint(company)
But if you try to access the dictionary, youll encounter a NameError
because the dictionary no longer exists.
A more appropriate method to delete all elements from a dictionary without deleting the dictionary itself is to use the clear()
method.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "active": True,}company.clear()print(company) # Output: {}
The code gives you the empty dictionary as the output. The del
will delete the whole object, and the clear()
method will just clear the content of the dictionary, but the object will remain.
Built-in Python dictionary methods
Python provides a set of built-in methods to make common dictionary operations like adding, deleting, and updating easier. These methods improve code performance and consistency. Some common methods include get()
, keys()
, values()
, items()
, pop()
, and update()
.
get()
The get()
method returns the value for a key if it exists in the dictionary or returns None
if the key does not exist. You can also set a default value, which will be returned when the key does not exist in the dictionary.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "products": ["crawlee", "actors", "proxy"],}print(company.get("name"))print(company.get("founder"))print(company.get("founder", "Sorry, key not exist!"))print(company["founder"])
Heres the code result:
Get method example of code result
In the above output, when you try to access the key name
, the value apify
is returned. When you try to access the key founder
, which does not exist in the dictionary, the value None
is returned. When you access the key founder
again, the default value that you set to return if the key is not found is returned. Finally, when you try to access the key without using the .get()
method, the program throws an error. This is why the .get()
method is useful.
keys()
This method returns a list of keys in a dictionary. It returns an iterable object (dict_keys
) that contains a list of all keys in the dictionary.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "products": ["crawlee", "actors", "proxy"],}print(company.keys()) # dict_keys(['name', 'year', 'solution', 'products'])
Often, this method is used to iterate through each key in the dictionary.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "products": ["crawlee", "actors", "proxy"],}for k in company.keys(): print(k)
Heres the code output:
Keys method example of code output
values()
Returns a list of all values in the dictionary. The values()
method returns a dict_values
object.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "products": ["crawlee", "actors", "proxy"],}print(company.values())# Output: dict_values(['apify', 2015, 'web scraping', ['crawlee', 'actors', 'proxy']])
items()
This method returns a list of key-value pairs as tuples, where the first item in each tuple is the key, and the second item is the value. The returned object is iterable, so this method is primarily used when you want to iterate through the dictionary.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "products": ["crawlee", "actors", "proxy"],}print(company.items())# Output: dict_items([('name', 'apify'), ('year', 2015), ('solution', 'web scraping'), ('products', ['crawlee', 'actors', 'proxy'])])
When you iterate through the dictionary.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "products": ["crawlee", "actors", "proxy"],}for k, v in company.items(): print(k, v)# or for x in company: print(x, company[x])
Heres the code output:
Items method example of code output
Note that when you change the value in the dictionary, the items
object will also be updated to reflect the changes.
company = { "name": "apify", "year": 2015, "solution": "web scraping", "products": ["crawlee", "actors", "proxy"],}pairs = company.items()print(pairs)company["year"] = 2023print(pairs)
Heres the code result:
Example of code result with changed value in the dictionary
pop()
The pop()
method removes a key from a dictionary if it is present and returns its associated value.
Example of code output pop method
The pop()
method raises an error if the key is not found.
Pop method example of error
But if you don't want this error to be raised, you can set a default value.
Pop method setting a default value
update()
The update() method is useful whenever you want to merge a dictionary with another dictionary or with an iterable of key-value pairs. Let's consider that the dictionary company
will be updated using the entries from the dictionary new_dict
. For each key in new_dict
:
If the key is not already present in the
company
, the key-value pair fromnew_dict
will be added to thecompany
.If the key is already present in the
company
, the corresponding value in thecompany
for that key is updated with the value fromnew_dict
.
company = {"name": "apify", "year": 2015, "solution": "web scraping"}new_dict = { "active": True, "solution": "web scraping and automation",}company.update(new_dict)print(company)
Heres the code output:
Update method example of code output
As shown above, the new key active
is added to the company
dictionary, and the solution
key is updated.
Now, new_dict
can also be specified as a list of tuples.
company = {"name": "apify", "year": 2015, "solution": "web scraping"}new_dict = (("active", True), ("solution", "web scraping and automation"))company.update(new_dict)print(company)
Heres the code result:
Update method with a list of tuples code result
Values to be merged can also be specified as a list of arguments.
company = {"name": "apify", "year": 2015, "solution": "web scraping"}new_dict = (("active", True), ("solution", "web scraping and automation"))company.update(active=True, solution="web scraping and automation")print(company)
Heres the code output:
Update method with values as a list of arguments code output example
fromkeys() method
The fromkeys()
method is used to create a dictionary from a given sequence of keys (which can be a string, tuple, list, etc.) and values. The value
parameter is optional, and if a value is not provided, None
is assigned to the keys. The fromkeys()
method returns a new dictionary with the specified sequence of keys and values.
keys = {"name", "year", "solution"}value = "apify"new = dict.fromkeys(keys, value)print(new) # Output: {'name': 'apify', 'solution': 'apify', 'year': 'apify'}
If a value is not provided, None
will be assigned as the value to all the keys.
keys = {"name", "year", "solution"}new = dict.fromkeys(keys)print(new)# Output: {'year': None, 'solution': None, 'name': None}
Now, let's take a look at one more feature provided by fromkeys()
. This time, use a mutable value.
keys = {"name", "year", "solution"}value = ["apify"]new = dict.fromkeys(keys, value)print(new)value.append(2015)print(new)
Heres the code output:
Fromkeys method code output example
In the above result, when we update the list value using append
, the keys are assigned with the new updated values. This is because each element is referencing the same memory address.
copy()
This method returns a copy of the existing dictionary. Note that modifications made to the copied dictionary won't affect the original one.
company = {"name": "apify", "year": 2015, "solution": "web scraping"}new_copy = company.copy()print(new_copy)new_copy["name"] = "apify technology"print(company)
Heres the code output:
Copy method example of code output
In the code, we are trying to modify the name of the new_copy
dictionary, but it does not affect the original dictionary (company
).
Iterating over dictionaries
The dictionary allows access to the data in O(1)
time. So, it is important to understand how to iterate over it so that you can access the data youve stored in the dictionary. Three commonly used methods for iterating over dictionaries are keys()
, values()
, and items()
.
Using loop with keys()
This method allows you to iterate through all the initialized keys. It returns a view object, which is basically a view of some data. You can iterate over this returned object without any problems. However, if you want to store the list of keys, you need to materialize it.
company = {"name": "apify", "year": 2015, "solution": "web scraping"}all_keys = company.keys()print(all_keys) # dict_keys(['name', 'year', 'solution'])# Materializing the keys into a list of keyskeys_list = list(company.keys())print(keys_list) # ['name', 'year', 'solution']
The first result is a view object, and the second result is a list of keys because you materialize the view object into a list.
Now, let's iterate over the dictionary, demonstrating two simple ways.
company = {"name": "apify", "year": 2015, "solution": "web scraping"}for key in company.keys(): print(key, company[key])for key in company: print(key, company[key])
Heres the code output:
Loop with keys example of code output
Note: When using the in
keyword with a dictionary, the dictionary invokes the __iter__ ()
method, which returns an iterator. This iterator is then used to iterate through the keys of the dictionary implicitly.
Using loop with values()
Like the keys()
method, the values()
method also returns a view object that allows you to iterate over the values. Unlike the keys()
method, this method provides only values. So, if you are not concerned about the keys, use this method.
company = {"name": "apify", "year": 2015, "solution": "web scraping"}for val in company.values(): print(val)# Output:""""apify2015web scraping"""
Using loop with items()
Similar to the previous method, the items()
method also returns a view object, but here you can iterate through the (key, value) pairs instead of iterating through either keys or values.
company = {"name": "apify", "year": 2015, "solution": "web scraping"}for item in company.items(): print(item)
Heres the code output:
Loop with items example of code output
The above code returns the key-value pairs. Now, to immediately assign both keys and values simultaneously, you can use tuple unpacking and extract them using variables.
company = {"name": "apify", "year": 2015, "solution": "web scraping"}for key, value in company.items(): print(key, value)
Heres the code result:
Loop with items assigning keys and values using variables code result example
Dictionary comprehensions
First, let's remind ourselves what comprehension is in Python. It simply means applying a specific kind of operation on each element of an iterable (tuple, list, or dictionary). Dictionary comprehension is similar to list comprehension, but it creates a dictionary instead of a list.
It is a useful feature that allows us to create dictionaries on a single line concisely and efficiently. The common uses of dictionary comprehension include constructing dictionaries, transforming existing dictionaries, and filtering dictionary content.
{key: value for (key, value) in iterable}
Suppose youve got a dictionary that contains the names and money of each person. Suppose you want to transform the dictionary's values, i.e., you want to increment each amount of money by 10 dollars.
person = {"satyam": 22, "john": 18, "elon": 19}# Dictionary comprehension approachnew_person = {name: money + 10 for name, money in person.items()}print(new_person) # {'satyam': 32, 'john': 28, 'elon': 29}
Suppose you want to filter all the person names whose money is less than 20 dollars.
person = {"satyam": 22, "john": 18, "elon": 19}new_person = {name: money for name, money in person.items() if money < 20}print(new_person) # {'john': 18, 'elon': 19}
Let's filter the data by using if
and else
with dictionary comprehension. Suppose you want to create a new dictionary where the amount of money less than 20 will get a 20% increase.
person = {"satyam": 22, "john": 18, "elon": 19}new_person = { name: money * 1.2 if money < 20 else money for name, money in person.items()}print(new_person) # {'satyam': 22, 'john': 21.6, 'elon': 22.8}
You can perform a lot of operations in one line using dictionary comprehension.
Advanced Python dictionary operations
Python dictionaries allow you to perform various advanced operations, such as handling missing keys using the get()
and setdefault()
methods, merging dictionaries, and working with nested dictionaries. This ultimately provides a lot of flexibility for working with data in a more structured way.
Handling missing keys with get() and setdefault()
Sometimes, users don't know if a key exists in a dictionary, and they try to access it. This can cause an error. There are a few ways to handle missing keys. One way is to use the get()
and setdefault()
methods to set a default value for the key. This way, you don't have to handle the error yourself.
The get()
method returns the associated value if the key is found in the dictionary. Otherwise, it returns the default value (which is None
by default), instead of raising an error. You can also specify a custom default value as the second argument.
company = {"name": "Apify", "year": 2015, "solution": "web scraping"}# Accessing a key using the get() methodprint(company.get("founder"))# Accessing a key using the get() method with a default valueprint(company.get("founder", "Sorry, key not found!"))# Accessing a key without using the get() methodprint(company["founder"])
Heres the code result:
Missing keys example of code output
Another method is setdefault()
. If the key is present in the dictionary, it returns the value of the key. Otherwise, this method inserts a new key with the default value passed as an argument in the method as its value.
# Create a dictionary to store person's informationperson = {"name": "Satyam", "age": 21}# If the 'age' key is present, retrieve its value; otherwise, set a default valueage = person.setdefault("age", "Key not found!")# If the 'city' key is not present, set it to the default value "Key not found!"city = person.setdefault("city", "Key not found!")print("Age:", age)print("City:", city)# The dictionary 'person' will be updated as the new key 'city' is addedprint("Updated dictionary:", person)
Heres the code output:
Using setdefault for missing keys code output example
In the above code, the age
key is already in the dictionary. We are trying to set the default value for the age
key, but this is impossible. So, the age
value remains the same, which is 21. We are also trying to set the default value for the city
key, which is not in the dictionary. So, the city
value is set to the default value, Key not found
. Now, if you try to access the city
key, the default value will be printed. The dictionary has been updated as the new key city
is added.
The main difference between get()
and setdefault()
is that get()
only returns the value of the key if it exists in the dictionary, while setdefault()
will set the key to the default value if it does not exist.
Merging dictionaries
Merging of dictionaries happens from right to left (A B). When there is a common key in both dictionaries, the value from the second dictionary overwrites the value in the first dictionary. As shown in the illustration below, key 1 exists in both dictionary A and dictionary B, but the value of key 1 in dictionary B overwrites the value of key 1 in dictionary A. This process occurs from right to left.
Merging dictionaries
Lets understand some ways to merge Python dictionaries.
From Python version 3.9 onward, we can use the merge (|
) and Update (|=
) operators. The merge (|
) operator creates a new dictionary with the keys and values from both of the given dictionaries. You can then assign this newly created dictionary to a new variable. The Update (|=
) operator adds the key-value pairs of the second dictionary to the first dictionary.
dict_a = {"name": "apify", "year": 2015, "solution": "web scraping"}dict_b = {"name":"apify tech", "active": True, "repos": 112}# Merge Operatorresult = dict_a | dict_bprint(result)# Update Operatordict_a |= dict_bprint(dict_a)
Heres the code output:
Merging dictionaries code output example
Another method is to merge by unpacking both dictionaries using double asterisks (**).
dict_a = {"name": "apify", "year": 2015, "solution": "web scraping"}dict_b = {"name":"apify tech", "active": True, "repos": 112}result = { **dict_a,** dict_b}print(result)
Heres the code result:
Merging dictionaries by unpacking them code result example
Another way is to copy one of the dictionaries and update it with other dictionaries.
dict_a = {"name": "apify", "year": 2015, "solution": "web scraping"}dict_b = {"name":"apify tech", "active": True, "repos": 112}copy_dict_a = dict_a.copy()copy_dict_a.update(dict_b)print(copy_dict_a)
Heres the code result:
Merging dictionaries by copying one of them code result example
Nested dictionaries
A nested dictionary is a collection of dictionaries within a single dictionary. In short, a nested dictionary is a dictionary inside another dictionary. Below, we have created a nested dictionary for two companies:
companies = { "Apify": { "founded_year": 2012, "HQ_location": "Prague, Czech Republic", "CEO": "Jan Curn", "products": ["Web Scraping", "Data Extraction", "Automation"], }, "Google": { "founded_year": 1998, "HQ_location": "Mountain View, California", "CEO": "Sundar Pichai", "products": ["Search", "Android", "YouTube"], },}
You can access individual items in a nested dictionary by specifying the key within multiple square brackets.
companies = { "Apify": { "founded_year": 2012, "HQ_location": "Prague, Czech Republic", "CEO": "Jan Curn", "products": ["Web Scraping", "Data Extraction", "Automation"], }, "Google": { "founded_year": 1998, "HQ_location": "Mountain View, California", "CEO": "Sundar Pichai", "products": ["Search", "Android", "YouTube"], },}print(companies["Apify"]["HQ_location"]) # Prague, Czech Republicprint(companies["Apify"]["CEO"]) # Jan Curn
If the key is not present, the program will raise an exception. To avoid this exception, you can use the get()
method.
companies = { "Apify": { "founded_year": 2012, "HQ_location": "Prague, Czech Republic", "CEO": "Jan Curn", "products": ["Web Scraping", "Data Extraction", "Automation"], }, "Google": { "founded_year": 1998, "HQ_location": "Mountain View, California", "CEO": "Sundar Pichai", "products": ["Search", "Android", "YouTube"], },}# Accessing the HQ location of 'Apify'print(companies["Apify"].get("HQ_location")) # Output: Prague, Czech Republic# Attempting to access a non-existent key ('Founder') in 'Apify'print(companies["Apify"].get("Founder")) # Output: None
You can change the value of a specific item in a nested dictionary.
companies = { "Apify": { "founded_year": 2012, "HQ_location": "Prague, Czech Republic", "CEO": "Jan Curn", "products": ["Web Scraping", "Data Extraction", "Automation"], }, "Google": { "founded_year": 1998, "HQ_location": "Mountain View, California", "CEO": "Sundar Pichai", "products": ["Search", "Android", "YouTube"], },}companies["Apify"]["founded_year"] = 2015companies["Apify"]["CEO"] = "Curn Jan"print(companies)
Heres the code result:
Nested dictionaries code result example
You can add or update nested dictionary items. If the key is not present in the dictionary, the key will be added. If the key is already present in the dictionary, its value is replaced by the new one.
companies = { "Apify": { "founded_year": 2012, "HQ_location": "Prague, Czech Republic", "CEO": "Jan Curn", "products": ["Web Scraping", "Data Extraction", "Automation"], }, "Google": { "founded_year": 1998, "HQ_location": "Mountain View, California", "CEO": "Sundar Pichai", "products": ["Search", "Android", "YouTube"], },}# Adding a new company ('Amazon') to the dictionarycompanies["Amazon"] = { "founded_year": 1994, "HQ_location": "Seattle, Washington", "CEO": "Andy Jassy", "products": ["eCommerce", "Amazon Web Services", "Kindle"],}print(companies)
Heres the code output:
Nested dictionary items code output example
Use the del
statement to delete elements from the nested dictionary. In the code below, we are trying to delete the Google
dictionary.
companies = { "Apify": { "founded_year": 2012, "HQ_location": "Prague, Czech Republic", "CEO": "Jan Curn", "products": ["Web Scraping", "Data Extraction", "Automation"], }, "Google": { "founded_year": 1998, "HQ_location": "Mountain View, California", "CEO": "Sundar Pichai", "products": ["Search", "Android", "YouTube"], },}del companies["Google"]print(companies)
Heres the code result:
Using del statement code result example
Real-world applications for Python dictionaries
Python dictionary is a very useful data structure and is used in many real-world scenarios because they are easy to use, flexible, and efficient.
Benefits
Ease of use: Python dictionary is a powerful data structure that makes it easy to store and retrieve data. They are easy to use, provide quick access to data, and make finding data much easier. With very little code, you can modify dictionaries, add and delete objects, and more.
Flexible: Python dictionaries are flexible and can store many different types of data, such as numbers, strings, and lists. This makes it easy to access and manipulate the data.
Efficiency: Python dictionaries use hash tables to store data, which allows them to find the value associated with a key quickly. Python dictionaries take very little space to store data, making them ideal for applications that need to access and manipulate large amounts of data easily. Python dictionary functions like
get()
andsetdefault()
let you efficiently look up data in a dictionary. Other functions likepop()
,update()
, andclear()
are efficient for manipulating data.
Example
Let's take a look at the real-life application where Python dictionaries are used a lot. This example shows how to store student data using a Python dictionary efficiently. You can access the student data without getting an error if the student information is not found. You can also list all the student information and remove specific student details.
class StudentDatabase: def __init__ (self): self.students = {} def add_student(self, student_id, name, grade): self.students[student_id] = {"name": name, "grade": grade} def get_student_info(self, student_id): return self.students.get(student_id, None) def list_all_students(self): for student_id, student_info in self.students.items(): print( f"Student ID: {student_id}, Name: {student_info['name']}, Grade: {student_info['grade']}" ) def remove_student(self, student_id): if student_id in self.students: del self.students[student_id] print("Student removed from the database.") else: print("Student not found in the database")def main(): student_manager = StudentDatabase() while True: print("\\nStudent Management Menu:") print("1. Add Student") print("2. Retrieve Student Information") print("3. List All Students") print("4. Remove Student") print("5. Exit") choice = input("Enter your choice: ") if choice == "1": student_id = input("Enter student ID: ") name = input("Enter student name: ") grade = input("Enter student grade: ") student_manager.add_student(student_id, name, grade) print("Student added to the database.") elif choice == "2": student_id = input("Enter student ID to retrieve: ") student = student_manager.get_student_info(student_id) if student: print( f"Student ID: {student_id}, Name: {student['name']}, Grade: {student['grade']}" ) else: print("Student not found in the database.") elif choice == "3": student_manager.list_all_students() elif choice == "4": student_id = input("Enter student ID to remove: ") student_manager.remove_student(student_id) elif choice == "5": break else: print("Invalid choice. Please try again.") print("Goodbye!")if __name__ == " __main__": main()
Heres the code output:
How to store student data using a Python dictionary code output
Similarly, Python dictionaries can be used in other real-life applications, such as:
Creating a contact book to store all of your contacts.
Building a user authentication service to store all of your users' data.
Best practices for Python dictionaries
Following best practices can help you get the most out of dictionaries and avoid common pitfalls. The best practices ensure that your code will remain maintainable, reliable, and perform at its best.
Ensuring unique keys
Keys in a Python dictionary must be unique. If you try to insert a duplicate key, the new value will overwrite the existing one. The most common and straightforward method to ensure unique keys is to check whether the key exists in the dictionary before inserting a new key-value pair. You can use the in
operator for this.
In the following code, we check if the key exists. If it does not exist, we simply insert it. Otherwise, we handle it accordingly, such as ignoring the new value, replacing the existing value with the new value, or raising an exception.
company = {"name": "Apify", "founded": 2012}key = "solution"# Check if the 'key' exists in the 'company' dictionaryif key not in company: # If it doesn't exist, add the 'key' with the value 'web scraping' company[key] = "web scraping"else: # Handle the case when 'key' already exists in the dictionary (duplicate key)
Mutable vs. immutable key types
Dictionary keys must be of an immutable type, such as integers, floats, strings, tuples, or Booleans. Lists and dictionaries cannot be dictionary keys because they are mutable. However, values can be of any type and used multiple times.
Mutable vs. immutable key types error example
The output is an Exception, what does unhashable mean?
It simply means that the Python interpreter is not able to generate a hash for the key given in the dictionary, whose data type is a list. So, the values of a dictionary can be of any type, but the keys must be of an immutable data type.
Performance considerations
Python dictionaries are an excellent choice for fast lookups, insertions, and deletions. However, some factors may affect their performance.
Use dictionary comprehension when creating dictionaries. Dictionary comprehension is more concise and readable than a loop, and it is also more efficient in some cases, especially for large datasets.
Flat dictionaries are faster than nested dictionaries. If you want to store nested data, consider using a different data structure, such as a list of dictionaries or a tuple of dictionaries.
When initializing a new dictionary, using
{}
is more efficient than callingdict()
. With{}
, there are no function call overheads. Callingdict()
requires Python to look up and execute a function, which incurs a slight performance penalty.
Python dictionary in use
Comparing dictionaries with other Python data structures
Python dictionary have their own unique characteristics and use cases when compared to other data structures like lists, sets, and tuples.
Differences and similarities with lists, sets, and tuples
Lists are the ordered collections of elements that can be modified after creation. Items can be accessed by index, and duplicates are allowed.
Sets are unordered collections of unique elements that cannot be modified after creation. Sets are commonly used for operations such as finding the union, intersection, or difference between sets.
Tuples are immutable ordered collections of elements that cannot be modified after creation. Tuples are often used when you want to ensure that a collection of items remains constant and in a specific order.
Dictionaries are the unordered collections of key-value pairs. The keys must be unique and hashable, and the values can be any type of data. Dictionaries can be modified after creation.
When to use dictionaries over other data structures
Python dictionaries provide a fast and efficient way to retrieve data by its key in constant time, O(1)
. Dictionaries do not allow duplicate keys, so you can be sure that each key in a dictionary is unique. This makes them an excellent choice for storing large amounts of data in memory.
When you need to access a specific element in a data structure, dictionaries are much faster than other data structures, such as lists. This is because the runtime for dictionary lookup operations is constant.
Here is a simple comparison of the runtimes for list and dictionary lookup operations:
List:
import time# Create a list containing numbers from 0 to 9,999,999number_list = [number for number in range(10**7)]# Measure the time taken to check if '5' is in the liststart_time = time.time()if 5 in number_list: print("5 is in the list")list_runtime = time.time() - start_timeprint(f"\\nList runtime (checking '3' in the list): {list_runtime} seconds.")# Measure the time taken to find the number '9,000,000' in the liststart_time = time.time()for number in number_list: if number == 9000000: breaklist_runtime = time.time() - start_timeprint(f"\\nList runtime (finding '9,000,000' in the list): {list_runtime} seconds.")
Heres the code output:
Comparison of the runtimes for list. Code output example
Dictionary:
import time# Create a dictionary with keys and valuesdictionary_data = {i: i * 2 for i in range(10**7)}# Measure the time taken to check if '5' is a key in the dictionarystart_time = time.time()if 5 in dictionary_data: print("Key '5' is in the dictionary.")dict_runtime = time.time() - start_timeprint( f"\\nDictionary runtime (retrieving the value for key '5'): {dict_runtime:.6f} seconds.")# Measure the time taken to retrieve the value for the key '9,000,000' from the dictionarystart_time = time.time()value = dictionary_data.get(9000000)dict_runtime = time.time() - start_timeprint( f"\\nDictionary runtime (retrieving the value for key '9,000,000'): {dict_runtime:.6f} seconds.")
Heres the code output:
Example of dictionary runtimes
Have you noticed that dictionaries perform much better than lists when looking up larger indexes? It took the dictionary almost no time to locate the number, while the list took around 1 second to perform the same operation.
Wrapping up
You learned in detail how to create, modify, and delete Python dictionaries, as well as some of the most commonly used dictionary methods and advanced Python dictionary operations. Start using these dictionary methods whenever you see a possibility. Build amazing projects using dictionaries and their methods, keeping best practices in mind.
Top comments (0)