Skip to main content

How to Check, Access and Remove Keys from Nested Dictionaries

Nested dictionaries (dictionaries within dictionaries) are common in Python for representing structured data.

This guide explores how to:

  • Check if a nested key exists.
  • Access nested dictionary values safely.
  • Remove keys from nested dictionaries, both in-place and by creating new dictionaries.

We'll use clear examples and emphasize best practices for working with these structures.

Checking for Nested Key Existence

There are two primary ways to check if a nested key exists without causing a KeyError:

Using try-except (Basic Approach)

The simplest way is to attempt to access the nested keys and catch the potential KeyError:

my_dict = {
'address': {
'country': 'Italy',
'city': 'Rome'
}
}

try:
city = my_dict['address']['city']
print(city) # Output: Rome
except KeyError:
print('The specified key does NOT exist')

try:
result = my_dict['not']['found']['key'] # Raises KeyError
except KeyError:
print('The specified key does NOT exist')
# Output: The specified key does NOT exist
  • If the key is found, the value is printed.
  • If the key is not found, the except block will handle the KeyError exception.

Using a Loop and get() (More Robust)

For a more robust and reusable solution, create a function that iteratively checks for each key in a sequence:

def keys_exist(dictionary, keys):
"""
Checks if a sequence of keys exists in a nested dictionary.

Args:
dictionary: The dictionary to check.
keys: A list or tuple of keys to check in order.

Returns:
True if all keys exist, False otherwise.
"""
current_level = dictionary
for key in keys:
if not isinstance(current_level, dict) or key not in current_level: # checks
return False # Key doesn't exist at this level
current_level = current_level[key] # Move one level deeper

return True # All keys found


my_dict = {
'address': {
'country': 'Italy',
'city': 'Rome'
}
}

print(keys_exist(my_dict, ['address', 'city'])) # Output: True
print(keys_exist(my_dict, ['key', 'not', 'found'])) # Output: False
  • The function iterates through the nested dictionary, moving from the initial dictionary, to the nested layers.
  • At each level, the function checks that current_level is a dictionary, and it contains the key we are looking for.
  • If either the current_level is not a dictionary or the key is missing, False is returned.

Accessing Nested Dictionary Values Safely

To avoid KeyError exceptions when accessing nested values, use the get() method with a default value (usually None or an empty dictionary):

my_dict = {
'address': {
'country': 'Italy',
'city': 'Rome'
}
}
result = my_dict.get('address', {}).get('city')
print(result) # Output: Rome

result = my_dict.get('key', {}).get('not', {}).get('found') # Chain `get` calls.
print(result) # Output: None
  • The get method accesses a key in a dictionary and returns the value, or returns a default value if the key is missing.
  • This method is used to avoid exceptions if a key is not found.
  • You can use multiple chained get() methods, and specify empty dictionaries as default values.

Removing Keys from Nested Dictionaries (In-Place)**

To modify the original dictionary and remove keys (both top-level and nested):

def remove_nested_keys(dictionary, keys_to_remove):
"""
Removes specified keys from a nested dictionary (in-place modification).
"""
for key in keys_to_remove:
if key in dictionary:
del dictionary[key] # Remove the key if it exists

for value in dictionary.values(): # Iterate over the values
if isinstance(value, dict): # Check if it is a dict
remove_nested_keys(value, keys_to_remove) # Recursive call

return dictionary # Return for convenience (though it's modified in-place)


my_dict = {
'address': {
'country': 'Italy',
'city': 'Rome',
},
'name': 'Anna',
'age': 23,
}

print(remove_nested_keys(my_dict, ['city', 'age']))
#Output: {'address': {'country': 'Italy'}, 'name': 'Anna'}
  • The method first iterates over all the keys that need to be removed and checks if they exist in the dictionary.
  • If the key exists, it is removed with del dictionary[key].
  • The method then checks all values of the keys for dictionary objects and calls itself recursively if it finds them.

Removing Keys from Nested Dictionaries (Creating a New Dictionary)

To create a new dictionary without modifying the original, use a recursive function with dictionary comprehensions:

def remove_nested_keys(dictionary, keys_to_remove):
"""
Removes specified keys from a nested dictionary, returning a NEW dictionary.
"""
new_dict = {}
for key, value in dictionary.items():
if key not in keys_to_remove:
if isinstance(value, dict):
new_dict[key] = remove_nested_keys(value, keys_to_remove) # Recursive call
else:
new_dict[key] = value
return new_dict

my_dict = {
' address': {
'country': 'Italy',
'city': 'Rome',
},
'name': 'Anna',
'age': 23,
}

result = remove_nested_keys(my_dict, ['country', 'name'])
print(result) # Output: {'address': {'city': 'Rome'}, 'age': 23}

result = remove_nested_keys(my_dict, ['city', 'age'])
print(result) # Output: {'address': {'country': 'Italy'}, 'name': 'Anna'}
  • This function creates a new dictionary, leaving the original my_dict unchanged.
  • It iterates through the key-value pairs of the input dictionary.
  • If a key is not in keys_to_remove, it's included in the new dictionary.
  • If a value is a dictionary itself, the function calls itself recursively to process the nested dictionary.