'Loading different subclasses from json

There's a good inheritance vs composition tutorial at https://realpython.com/inheritance-composition-python/ which gives an example of extending the base class Employee into two subclasses, SalaryEmployee and HourlyEmployee. This gives you different methods on each employee type such as paying by the hour or paying by the month.

You then instantiate each employee individually using the correct subclass:

john = hr.SalaryEmployee(id=1, name='John Smith', monthly_salary=1500)
jane = hr.HourlyEmployee(id=2, name='Jane Doe', working_hours=40, hourly_salary=15)

If I am loading the employee data from a data structure that specifies the employeetype within each record, e.g.:

employee_data = [
    {
        'name': 'John Smith',
        'id' : 1,
        'type' : 'SalaryEmployee',
        'monthly_salary' : 1500
    },
    {
        'name' : 'Jane Doe',
        'id' : 2,
        'type' : 'HourlyEmployee',
        'working_hours' : 40,
        'hourly_salary' : 15
    }
]

...how do I dynamically assign the correct subclass to each employee?

A set of "if employee['type'] == ..." statements would work, but means that whenever we add a new subclass we have to modify the instantiation code which seems inelegant. Is there a more pythonic way?

I'm looking for something along the lines of

employee_objects = [CorrectSubClassOfEmployee(**x) for x in employee_data]

I absolutely cannot be the first person to ask this, but my google-fu is not turning up the right answer

Thanks!



Solution 1:[1]

You will want getattr:

employee_objects = [hr.getattr(x['type'])(**x) for x in employee_data]

(Obviously, the appropriateness of the **x will depend on how you've written the constructor for your (sub)class)

Solution 2:[2]

Use a dict

employee_subclasses = {
    'SalaryEmployee': hr.SalaryEmployee,
    'HourlyEmployee': hr.HourlyEmployee,
}
employee_objects = [employee_subclasses[x.pop('type')](**x) for x in employee_data]

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alex
Solution 2 Iain Shelvington