Skip to main content

How to Create Class Instances from Dictionaries in Python

This guide explains how to create instances of a Python class from a dictionary, where the dictionary's keys correspond to the class's attributes. We'll cover the recommended approach using dictionary unpacking and a more dynamic (but less recommended) approach using setattr().

The most Pythonic and readable way to create a class instance from a dictionary is to define the expected attributes in the class's __init__ method and then use dictionary unpacking (**) when creating the instance:

class Developer():
def __init__(self, name, salary, language):
self.name = name
self.salary = salary
self.language = language

my_dict = {'name': 'tom nolan', 'salary': 50, 'language': 'Python'}
tom = Developer(**my_dict) # Unpack the dictionary

print(tom.name) # Output: tom nolan
print(tom.salary) # Output: 50
print(tom.language) # Output: Python
  • __init__(self, name, salary, language): The constructor explicitly defines the expected attributes. This is good for clarity and maintainability.
  • tom = Developer(**my_dict): The double asterisk (**) unpacks the dictionary my_dict into keyword arguments. This is equivalent to writing Developer(name='tom nolan', salary=50, language='Python').

Handling Missing Keys​

If the dictionary might be missing some keys, you have two main options:

  • Provide default values in __init__:

    class Developer():
    def __init__(self, name, salary=0, language='Python'): # Default values
    self.name = name
    self.salary = salary
    self.language = language

    my_dict = {'name': 'tom nolan'} # Missing 'salary' and 'language'
    tom = Developer(**my_dict)
    print(tom.salary) # Output: 0 (default value)
    print(tom.language) # Output: Python
    • The code now handles the default values using default arguments in the __init__.
  • Use dict.get() with defaults (less common for constructors): You could technically use dict.get() inside the __init__, but it's less readable than default arguments:

    class Developer:
    def __init__(self, data_dict):
    self.name = data_dict.get('name', 'Unknown') # Less recommended for init
    self.salary = data_dict.get('salary', 0)
    self.language = data_dict.get('language', 'Python')

    my_dict = {'name': 'tom nolan'} # Missing some values
    tom = Developer(my_dict)

Handling Extra Keys​

If the dictionary might contain extra keys that aren't attributes of your class, those extra keys will be ignored when you use ** unpacking with a defined __init__. This is usually the desired behavior. If you need to handle those extra keys, the dynamic setattr approach (described below) might be more appropriate.

Using setattr() (Dynamic, but Less Readable)​

You can dynamically create attributes based on all keys in a dictionary using setattr():

class Developer():
def __init__(self, dictionary):
for key, value in dictionary.items():
setattr(self, key, value) # set attribute

my_dict = {'name': 'tom nolan', 'salary': 50, 'language': 'Python'}
tom = Developer(my_dict)

print(tom.name) # Output: tom nolan
print(tom.salary) # Output: 50
print(tom.language) # Output: Python
  • setattr(self, key, value): This dynamically sets an attribute named key on the object self to the given value.
  • The __init__ method takes the dictionary and sets the attributes by looping through all key-value pairs.
warning

Drawbacks of setattr() in this context:

  • Less Readable: It's not immediately obvious which attributes the class will have. You have to examine the input dictionary to understand the object's structure.
  • Less Maintainable: Changes to the expected data structure (the dictionary keys) aren't reflected in the class definition.
  • Potential for Errors: If the dictionary contains keys that aren't valid Python identifiers (e.g., keys with spaces), you'll run into problems. (See the next section for how to handle this.)
  • Type Hinting: Type hinting and IDE support becomes much harder with the dynamic approach.

Handling Keys with Spaces or Invalid Characters​

If your dictionary keys might contain spaces or other characters that are invalid in Python attribute names, you'll need to sanitize them:

class Developer():
def __init__(self, dictionary):
for key, value in dictionary.items():
# Replace spaces with underscores, and ensure it's a valid identifier
safe_key = key.replace(' ', '_')
# Could add more validation here, e.g.
# if safe_key.isidentifier():
setattr(self, safe_key, value)

my_dict = {'first name': 'tom nolan', 'salary': 50, 'language': 'Python'}
tom = Developer(my_dict)

print(tom.first_name) # Output: tom nolan
print(tom.salary) # Output: 50
print(tom.language) # Output: Python
  • The replace method is used to change the name of the keys before setting them as attributes.