In this post I am going to discuss how accessing a value in adict
can easily introduce a bug in your code and how to fix it.
Access
One of the most common scenarios with dictionaries is accessing a value.
value=my_dict[key]
Problem: Ifkey
doesn't exist inmy_dict
, the code will raise aKeyError
Solution: To avoid this scenario you have three options:
Check if
key
exists before accessingifkeyinmy_dict:value=my_dict[key]
Wrap the access in
try-except
blocktry:value=my_dict[key]exceptKeyError:...
Use Python'sget function to avoid checking for
key
indict
value=my_dict.get(key)
Since,get
option (3) looks the neatest, I tend to use that the most.
Now, suppose for a function I am writing, I am accessing a value fromdict
but I only want to proceed if the given key exists in thedict
.
I would write something like this:
value=my_dict.get(key)ifnotvalue:raiseMyError('Found bad key')# continue with code
At first glance, the code looks fine, but I have introduced a bug in it.
Let me illustrate with an example:
# Assume my_dict as:my_dict={'key1':'value1','key3':[],}
Key | Behavior | Expected? |
---|---|---|
key1 | Regular code execution | Yes |
key2 | raisesMyError | Yes |
key3 | raisesMyError | No |
key2
raises the exception sinceget
function will returnNone
by default for non-existing keys.key3
exists in thedict
however my code will still throw an error becauseif not []
is alsoTrue
, leading to unintentional behavior.
Quick Bad Fix
Reading points aboutkey2
andkey3
from above, modifying the validation condition seems like the most obvious fix:
value=my_dict.get(key)ifvalueisNone:raiseMyError('Found bad key')
This, however, only fixes one symptom/effect of the bug that is when the value is an empty data type like''
or[]
. If the value inmy_dict
isNone
the above code will still raise the error.
Fix
Before writing a fix for your code, it is usually a good idea to think about the root cause of the bug, rather than the symptoms that are showing up. In our case, it was not theif
condition that was causing the bug - it was theget
function.
I only want to proceed if the given key exists in the
dict
To encode the described behavior the correct code block would look something like this:
ifkeyinmy_dict:value=my_dict[key]# rest of codeelse:raiseMyError('Found bad key')
Learning
- Capturing intent is critical in writing robust code.
- First step to fixing bugs should be to list assumptions and work from there.
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse