This text discusses three methods for accessing Python dictionary values: subscript notations, the get method, and the setdefault method, along with best practices for using each.
Abstract
The text begins by explaining the usefulness of dictionaries in Python and their ability to store key-value pairs. It then introduces the problem of accessing dictionary values when keys may not exist, leading to a KeyError exception. To avoid this, the text suggests using the get method as an alternative to subscript notations, as it allows for a default value to be set when the key is not found in the dictionary. The setdefault method is also mentioned, but it is generally not recommended due to its confusing name and implicit operations. The text concludes by discussing the defaultdict class, which can be used when iteratively accessing dictionary items and knowing the proper default value for missing keys.
Bullet points
Dictionaries in Python store key-value pairs and can be used to hold related items in a matched order.
Subscript notations can be used to access dictionary values, but they can raise a KeyError exception when the specified key is not in the dictionary.
The get method can be used to avoid the KeyError exception and set a default value when the key is not found in the dictionary.
The setdefault method is similar to the get method, but it is generally not recommended due to its confusing name and implicit operations.
The defaultdict class can be used when iteratively accessing dictionary items and knowing the proper default value for missing keys.
3 Ways To Access Python Dictionary Values
Take advantage of the flexibility that Python has to offer
Dictionaries are one of my favorite data types in Python. The major reason is that they store key-value pairs. Essentially, they can be used to hold two categories of information with related items in a matched order.
For instance, let’s say we have the following dictionary to store the grades of some students:
grades = {"Anne": 98, "John": 95, "Bella": 97}
This dictionary holds the following two sets of information: the students (names as the keys) and the grades. In addition, each student is associated with their own grade.
There are multiple approaches to retrieving the values stored in a dictionary. In this article, we’ll talk about them. More importantly, we’ll discuss the best practices.
Subscript Notations
The first approach to accessing a student’s grade is to use the subscript notation method, as shown below:
>>>grades["Anne"]
98
>>>grades["John"]
95
The major advantage of this method is that it’s very straightforward. If you have used dictionaries or dictionary-like data structures in other languages, such as JavaScript, Kotlin, or Swift, you’re probably very familiar with this approach. Thus, it can be very natural for you to use this approach when you need to access items of a dictionary.
However, there is a potential issue, as shown below:
When you’re trying to access a key that doesn’t exist in the dictionary, you’ll encounter the KeyError exception. When it’s not handled, your program will crash.
Best practice: Use subscript notations for dictionaries that you create or those for which you’re sure about the keys.
The get Method
Given the aforementioned problem with subscript notations, some people may have tried the following solution:
name_to_check = "some name"
if name_to_check in grades:
grade = grades[name_to_check]
else:
grade = "A default value"
This solution can certainly help avoid the KeyError exception, but it’s a little cumbersome. A better solution, in this case, is to use the get method of dictionaries. To use the get method, we specify the name of the key and a default value when the key isn’t in the dictionary.
The following code snippet shows you some examples of using get:
>>> grades.get("Anne")
98
>>> grades.get("Zoe", 0)
0
>>> grades.get("Zoe")
None (Noneis automatically hidden in an interactive console)
As shown above, the get method does offer the advantage of not raising the KeyError exception when the specified key isn’t in the dictionary. More importantly, it allows you to set a proper default value when the key doesn’t exist. Theoretically, you can use the get method whenever you retrieve values from dictionaries, but I prefer subscript notations whenever possible because I find them to be more readable.
However, there are scenarios where the get method can be very handy. One such scenario is when I need to deal with the variable keyword arguments in a function definition. Suppose you’re building a Python package that has the following API function:
As shown above, this function is flexible by supporting many different keyword parameters besides two positional arguments. For clarity, I don’t want to list all of these keyword arguments in my function definition. After all, I know what default values I want to set when these keyword parameters are omitted by the API users.
Best practice: Use the get method with dictionaries that you don’t have direct control over, such as those used in a function call to your APIs. You’ll know what default values are appropriate in these cases.
The setdefault Method
When people talk about alternatives to the get method, some may mention the setdefault method. This method is very similar to the get method because it also takes two parameters: the key (required) and a default value (optional) as the fallback. The fallback value will be returned when the key isn’t in the dictionary, while when the key is in the dictionary, the key’s value will be returned. Observe this feature below:
>>> grades.setdefault("Anne")
98>>> grades.setdefault("Danny", 0)
0>>> grades.setdefault("Ashley")
None (Noneis automatically hidden in an interactive console)
The code snippet above shows you that the behaviors of the setdefault method are similar to those of the get method. However, what makes setdefault differ from get is that when you call setdefault, an additional operation (dict[key] = default_value) occurs when the key isn’t in the dictionary. Observe this effect below:
We previously called setdefault with the keys “Anne”, “Danny”, and “Ashley”. Because “Danny” and “Ashley” were not in the dictionary when we called them, the following two operations occurred under the hood:
grades["Danny"] =0
grades["Ashley"] = None
Typically, I don’t recommend using the setdefault method. Not only is the name confusing — we don’t typically expect things returned by calling a method involving setting a value — but there is also an implicit operation (i.e. setting the default value if the key doesn’t exist) that many people may not know.
Best practice: Avoid using the setdefault method. It’s rarely needed.
The defaultdict Alternative
In the previous sections, we focused on solutions that are applicable to the dict class. However, besides the dict class, there is another dictionary type called defaultdict that is a subclass of dict. It’s available in the collections module. An example can help us understand this class:
Unlike the dict class constructor, defaultdict has a parameter named default_factory that is a zero-parameter function called when you’re accessing a key that is not in the dictionary. In our example, int is called to create a grade of zero (because int() evaluates to zero) when you’re accessing a student’s grade when the student isn’t in the dictionary. Observe this feature below:
>>>grades_default["Lily"]
0
One thing to note is that defaultdict operates like the setdefault method in the sense that the value created by the default_factory will be set to the key that wasn’t in the dictionary. For instance, after accessing “Lily”’s grade, the dictionary gets updated, as shown below:
Given the similarities between the setdefault method and the defaultdict class, they can have the following similar usage. Suppose that we want to create a dictionary object that uses the students’ initials as the keys, while the names with the same initials go with each key:
# Use the setdefault with a dict object
students_by_initial0 = {}
fornamein grades.keys():
group = students_by_initial0.setdefault(name[0], [])
group.append(name)
The code snippet above uses the setdefault method with a dict object. Let’s see how we can implement the same functionality with the defaultdict class:
# Use the defaultdict class
students_by_initial1 = defaultdict(list)
for namein grades.keys():
students_by_initial1[name[0]].append(name)
As you can imagine, if the same functionality is to be implemented by a regular dict class with an intermediate step of checking the existence of a key, it’ll be more complicated, as shown below:
Best practice: Use the defaultdict class when you have to access the items of the dictionary object iteratively, such as grouping in the example. In addition, you should know the proper default value when a key is missing. Otherwise, you can use the dict type.
Conclusion
In this article, we reviewed different approaches to accessing the values in a dictionary, with a special focus on dealing with cases where keys may not exist in the dictionary. In essence, each of these approaches has its own use scenario. Thus, choosing the best one is really dependent on your use case.