Search code examples
pythonexceldictionaryoopinput

Automated and scalable approach to store each dictionary item into class (instance) attributes with same keys and values?


I have a dictionary input_dict={'foo1':3, 'foo2':6} and I want to store its contents in an instance of class matClass such that mat.foo1=3, mat.foo2=6, etc...

I need this process to be automated since the dictionary may change in size depending on user inputs.

The code below iterates through the dictionary items and uses setattr to iteratively create class attributes with the same key and value as the dictionary. The if statement is there to check that the variables inputted by the user are actually supported by the rest of the code.

input_dict = {'foo1':3, 'foo2':6}

class matClass:
    allowed_input = ['foo1', 'foo2']

    def __init__(self):
        pass

    def import_data(self, input_dict):
        if set(list(input_dict.keys())).issubset(self.allowed_input):
            for key, value in input_dict.items():
                setattr(self, key, value)

mat = matClass()
mat.import_data(input_dict)

Is there a cleaner way to do this? Are there hidden dangers to this approach?

I am not necessarily bound to dictionaries, I could use dataframes if more convenient.


Solution

  • Looks like you want a limited subset of keys/values from the input dictionary.

    So, why not create a dictionary to contain relevant data then override __getattr__ to access them?

    Something like this:

    from typing import Any
    
    
    class matClass:
        ALLOWED = {'foo1', 'foo2'}
        def __init__(self):
            self._dict = dict()
            self.foo3 = 99
        def import_data(self, input_dict: dict):
            for key, value in input_dict.items():
                if key in matClass.ALLOWED:
                    self._dict[key] = value
        def __getattr__(self, __name: str) -> Any:
            try:
                return self._dict[__name]
            except KeyError:
                return self.__getattribute__(__name)
    
    _dict = {
        'foo1': 1,
        'foo2': 2,
        'foo3': 3
    }
    
    mc = matClass()
    
    mc.import_data(_dict)
    
    print(mc.foo1)
    print(mc.foo2)
    print(mc.foo3)
    

    Output:

    1
    2
    99