0

Suppose I have a python class like:

class User:
    name = None
    id = None
    dob = None
    
    def __init__(self, id):
        self.id = id

Now I am doing something like this:

userObj = User(id=12) # suppose I don't have values for name and dob yet
## some code here and this code gives me name and dob data in dictionary, suppose a function call
user = get_user_data() # this returns the dictionary like {'name': 'John', 'dob': '1992-07-12'}

Now, the way to assign data to user object is userObj.name = user['name'] and userObj.dob = user['dob']. Suppose, User has 100 attributes. I will have to explicitly assign these attributes. Is there an efficient way in Python which I can use to assign the values from a dictionary to the corresponding attributes in the object? Like, name key in the dictionary is assigned to the name attribute in the object.

Muhammad Muaaz
  • 164
  • 1
  • 13
  • Are you just trying to set the dict keys to variables that already exist in the class or are you trying to *create* variables in the class? Because dynamically creating variables is definitely the wrong way to do this. If you are just trying to set variable values, then that's something we can discuss. – Rashid 'Lee' Ibrahim Sep 02 '20 at 13:07
  • I am setting the values for class variables which already exist. – Muhammad Muaaz Sep 02 '20 at 13:27
  • I think this is what you need: https://stackoverflow.com/questions/68417319/initialize-python-dataclass-from-dictionary – ABDULVAHAB Kharadi Nov 23 '22 at 13:11

5 Answers5

1

First, there is no need to predeclare properties in python.

class Foo:
   bar: int # This actually creates a class member, not an instance member
   ...

If you want to add values to a class instance just use setattr()

d = {
  'prop1': 'value1',
  'prop2': 'value2',
  'prop2': 'value2'
}

x = Foo()

for prop in d.keys():
  setattr(x, prop, d[prop])
mageos
  • 1,216
  • 7
  • 15
  • It is like calling the __init__ method. which I don't want to. I want to assign values after the user instance is created (update the instance) – Muhammad Muaaz Sep 02 '20 at 13:18
1

1. Modify the Class definition

class User():
    def __init__(self, id):
        self.data = {"id":id}
userObj = User(id=12)

2. Update the dict()

user = {"name":"Frank", "dob":"Whatever"} # Get the remaining data from elsewhere
userObj.data.update(user) # Update the dict in your userObj
print(userObj.data)
Here you go !
1

Instead of mapping a dict to the variable keys. You can use setattr to set variables in an object.

class User:
    name = None
    id = None
    dob = None

    def __init__(self, id):
        self.id = id

    def map_dict(self, user_info):
        for k, v in user_info.items():
            setattr(self, k, v)

Then for boiler code to use it.


userObj = User(id=12)
user_dict = {
    'name': 'Bob',
    'dob': '11-20-1993',
    'something': 'blah'
}

userObj.map_dict(user_dict)
Rashid 'Lee' Ibrahim
  • 1,357
  • 1
  • 9
  • 21
0
class User(dict):
    def __init__(self, *args, **kwargs):
        super(User, self).__init__(*args, **kwargs)
        self.__dict__ = self

and then just get your dictionary and do:

userObj  = User(dictionary)

EDIT: user the function setattr() then

[setattr(userObj, key, item) for key,item in dict.items()]
Capie
  • 976
  • 1
  • 8
  • 20
  • It is like calling the `__init__` method. which I don't want to. I want to assign values after the user instance is created (update the instance). – Muhammad Muaaz Sep 02 '20 at 13:17
0

In Case you REALLY need to

This solution is for the case, other solutions dont work for you and you cannot change your class.

Issue

In case you cannot modify your class in any way and you have a dictionary, that contains the information you want to put in your object, you can first get the custom members of your class by using the inspect module:

import inspect
import numpy as np
members = inspect.getmembers(User)

Extract your custom attributes from all members by:

allowed = ["__" not in a[0] for a in members]

and use numpy list comprehention for the extraction itself:

members = np.array(members)["__" not in a[0] for a in members]

Modify the user

So lets say you have the following user and dict and you want to change the users attributes to the values in the dictionary (behaviour for creating a new user is the same)

user = User(1)
dic = {"name":"test", "id": 2, "dob" : "any"}

then you simply use setattr():

for m in members:
setattr(user, m[0], dic[m[0]])

For sure there are better solutins, but this might come in handy in case other things dont work for you

Update

This solution uses the attribute definitions based on your class you use. So in case the dictionary has missing values, this solution might be helpful. Else Rashids solution will work well for you too

MichaelJanz
  • 1,775
  • 2
  • 8
  • 23