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.