Using dot "." notation to access dictionary keys in Python

avatar
Borislav Hadzhiev

Last updated: Apr 9, 2024
5 min

banner

# Table of Contents

  1. Using dot "." notation to access dictionary keys in Python
  2. Returning None for non-existent keys instead of raising an error
  3. Use dot "." notation to access dictionary keys using __dict__
  4. An AttributeError exception is raised when a non-existent key is accessed
  5. Using dot "." notation to access nested dictionary keys

# Using dot "." notation to access dictionary keys in Python

To use dot notation to access dictionary keys:

  1. Extend the dict class when defining a class.
  2. Set the __getattr__ method to dict.__getitem__.
  3. Redirecting attribute access to dict.__getitem__ allows us to use dot notation to access dictionary keys.
main.py
class AttributeDict(dict): __getattr__ = dict.__getitem__ __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__ my_dict = {'id': 1, 'website': 'bobbyhadz.com', 'topic': 'Python'} new_dict = AttributeDict(my_dict) print(new_dict.website) # ๐Ÿ‘‰๏ธ bobbyhadz.com print(new_dict.topic) # ๐Ÿ‘‰๏ธ Python new_dict.author = 'Borislav Hadzhiev' # ๐Ÿ‘‡๏ธ {'id': 1, 'website': 'bobbyhadz.com', 'topic': 'Python', 'author': 'Borislav Hadzhiev'} print(new_dict) del new_dict.author # ๐Ÿ‘‡๏ธ {'id': 1, 'website': 'bobbyhadz.com', 'topic': 'Python'} print(new_dict)

using dot notation to access dictionary keys

The code for this article is available on GitHub

The AttributeDict class extends the built-in dict class.

We set the __getattr__ method to dict.__getitem__ to access a dictionary's keys as attributes.

The __getattr__ method is called when the default attribute access fails with an AttributeError.

In other words, __getattr__() gets called only for attributes that don't exist.

The dict.__getitem__ method is called when we access a dictionary key using square brackets, e.g. my_dict['name'] calls my_dict.__getitem__('name').

We set the __getattr__ method in the AttributeDict class to dict.__getitem__, so any time the user tries to access an attribute that doesn't exist, the dict.__getitem__ method is called.

We used the same approach to be able to use dot notation when setting and deleting keys from the dictionary.

main.py
class AttributeDict(dict): __getattr__ = dict.__getitem__ __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__ my_dict = {'id': 1, 'website': 'bobbyhadz.com', 'topic': 'Python'} new_dict = AttributeDict(my_dict) # โœ… Add a key to the dictionary new_dict.author = 'Borislav Hadzhiev' # ๐Ÿ‘‡๏ธ {'id': 1, 'website': 'bobbyhadz.com', 'topic': 'Python', 'author': 'Borislav Hadzhiev'} print(new_dict) # โœ… delete a key from the dictionary del new_dict.author # ๐Ÿ‘‡๏ธ {'id': 1, 'website': 'bobbyhadz.com', 'topic': 'Python'} print(new_dict)
The code for this article is available on GitHub

The object.__setattr__ method is called when an attribute assignment is attempted.

We set the method to dict.__setitem__ which is called when a key is added to a dictionary.

For example, my_dict['key'] = 'value' calls my_dict.__setitem__('key', 'value').

The object.__delattr__ method is called when an attribute is deleted using the del operator.

We set the method to dict.__delitem__ which is called when the user deletes a key from a dictionary.

For example, del my_dict['key'] calls my_dict.__delitem__('key') under the hood.

# Returning None for non-existent keys instead of raising an error

The dict.__getitem__ method raises a KeyError when we access a key that doesn't exist in the dictionary.

If you'd rather return None for non-existent keys, set __getattr__ to dict.get.

main.py
class AttributeDict(dict): __getattr__ = dict.get __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__ my_dict = {'id': 1, 'website': 'bobbyhadz.com', 'topic': 'Python'} new_dict = AttributeDict(my_dict) print(new_dict.example) # ๐Ÿ‘‰๏ธ None print(new_dict.website) # ๐Ÿ‘‰๏ธ bobbyhadz.com print(new_dict.topic) # ๐Ÿ‘‰๏ธ Python

returning none for non existing keys instead of raising an error

The code for this article is available on GitHub

The dict.get() method returns the value for the given key if the key is in the dictionary, otherwise a default value is returned.

The method takes the following 2 parameters:

NameDescription
keyThe key for which to return the value
defaultThe default value to be returned if the provided key is not present in the dictionary (optional)

If a value for the default parameter is not provided, it defaults to None, so the get() method never raises a KeyError.

Alternatively, you can use the __dict__ attribute.

# Use dot "." notation to access dictionary keys using __dict__

This is a three-step process:

  1. Extend the dict class when defining a class.
  2. Call the constructor of the dict class in your user-defined class.
  3. Set the __dict__ attribute to the current instance.
main.py
class AttributeDict(dict): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.__dict__ = self my_dict = {'id': 1, 'website': 'bobbyhadz.com', 'topic': 'Python'} new_dict = AttributeDict(my_dict) print(new_dict.website) # ๐Ÿ‘‰๏ธ bobbyhadz.com print(new_dict.topic) # ๐Ÿ‘‰๏ธ Python # โœ… add a key to the dictionary new_dict.author = 'Borislav Hadzhiev' # ๐Ÿ‘‡๏ธ {'id': 1, 'website': 'bobbyhadz.com', 'topic': 'Python', 'author': 'Borislav Hadzhiev'} print(new_dict) # โœ… delete a key from the dictionary del new_dict.author # ๐Ÿ‘‡๏ธ {'id': 1, 'website': 'bobbyhadz.com', 'topic': 'Python'} print(new_dict)
The code for this article is available on GitHub

The first line in the class's __init__() method runs the constructor of the dict class with the provided arguments. By doing this, our AttributeDict class behaves like a dictionary.

The self.__dict__ = self line sets the __dict__ attribute to the current instance.

By default, the __dict__ attribute returns a dictionary containing the object's properties and values.

In our case, the __dict__ attribute points to a subclass of dict that allows for attribute access.

# An AttributeError exception is raised when a non-existent key is accessed

Something to note when using this approach is that when you use dot notation to access a key that is not present in the dictionary, an AttributeError is raised instead of a KeyError.

main.py
class AttributeDict(dict): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.__dict__ = self my_dict = {'id': 1, 'website': 'bobbyhadz.com', 'topic': 'Python'} new_dict = AttributeDict(my_dict) # โ›”๏ธ AttributeError: 'AttributeDict' object has no attribute 'example' print(new_dict.example)

If you need to access nested dictionary keys as attributes, use the class from the next code snippet.

# Using dot "." notation to access nested dictionary keys

To use dot notation to access nested dictionary keys:

  1. Iterate over the dictionary's items in the __init__ method of a class.
  2. If the key has a value of type dict, instantiate the class with the value.
  3. Otherwise, set the key to the value.
main.py
class Struct: def __init__(self, **kwargs): for key, value in kwargs.items(): if isinstance(value, dict): self.__dict__[key] = Struct(**value) else: self.__dict__[key] = value my_dict = { 'name': { 'first': 'bobby', 'last': 'hadz', }, 'website': 'bobbyhadz.com' } obj = Struct(**my_dict) print(obj.name.first) # ๐Ÿ‘‰๏ธ bobby print(obj.name.last) # ๐Ÿ‘‰๏ธ hadz print(obj.website) # ๐Ÿ‘‰๏ธ bobbyhadz.com
The code for this article is available on GitHub

The Struct class takes keyword arguments and uses the __dict__ attribute on the object to convert the nested dictionary to an object.

On each iteration, we check if the current key points to a dictionary and if it does, we recursively pass the dictionary to the Struct class.

If the key doesn't point to a nested dictionary, we add it to the __dict__ attribute.

You can access nested attributes on the object using dot notation.

If you try to access an attribute that is not present on the object, an AttributeError is raised.

I've also written an article on how to use a variable to access a dictionary key.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev