35

Is there a built-in function/operator I could use to unpack values from a dictionary and assign it into instance variables?

This is what I intend to do:

c = MyClass()
c.foo = 123
c.bar = 123

# c.foo == 123 and c.bar == 123


d = {'bar': 456}
c.update(d)

# c.foo == 123 and c.bar == 456

Something akin to dictionary update() which load values from another dictionary but for plain object/class instance?

chakrit
  • 61,017
  • 25
  • 133
  • 162

4 Answers4

51

there is also another way of doing it by looping through the items in d. this doesn't have the same assuption that they will get stored in c.__dict__ which isn't always true.

d = {'bar': 456}
for key,value in d.items():
    setattr(c,key,value)

or you could write a update method as part of MyClass so that c.update(d) works like you expected it to.

def update(self,newdata):
    for key,value in newdata.items():
        setattr(self,key,value)

check out the help for setattr

setattr(...)
    setattr(object, name, value)
    Set a named attribute on an object; setattr(x, 'y', v) is equivalent to
    ''x.y = v''.
ViaTech
  • 2,143
  • 1
  • 16
  • 51
Jehiah
  • 2,739
  • 22
  • 18
  • 3
    I already know about setattr... Can you explain more on why some items would not be in __dict__ ? I actually ended up still using this kind of loop+setattr because __dict__ somehow wasn't available. – chakrit Jan 03 '09 at 07:39
  • 7
    sure, the main difference is between class attributes and instance attributes. Only the latter are in `__dict__`. so if you have class Test: a = 1 t = Test() the object `t` has an empty `__dict__` because a is a class attribute t.b = 2 now it has a `__dict__` of `{'b':2}` – Jehiah Jan 07 '09 at 22:51
  • and where are class attributes stored? in `Test.__dict__` I suppose? (it would be ok) – n611x007 Apr 26 '13 at 15:07
36

Have you tried

f.__dict__.update( b )

?

S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • 1
    http://www.python.org/doc/2.5.2/ref/types.html or http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy. The section titled "classes" is pretty explicit on precisely how this works. – S.Lott Jan 01 '09 at 21:23
  • 11
    This will silently misbehave when a class attribute isn't stored in the instance's `__dict__`. E.g., properties and class attributes. In general, Jehiah's answer is safer. – Jon-Eric Feb 09 '12 at 16:19
  • 1
    setattr is the most preferable way to go here. Using internal object.__dict__ is not recommended. – qubird Nov 24 '17 at 14:12
  • this misbehaved for me exactly as @Jon-Eric described – riemann_lebesgue Jun 27 '22 at 18:12
9

Also, maybe it would be good style to have a wrapper around the dict's update method:

def update(self, b):
    self.__dict__.update(b)

PS: Sorry for not commenting at @S.Lott 's post but I don't have the rep yet.

Community
  • 1
  • 1
hyperboreean
  • 8,273
  • 12
  • 61
  • 97
1

You can try doing:

def to_object(my_object, my_dict):
    for key, value in my_dict.items():
        attr = getattr(my_object, key)
        if hasattr(attr, '__dict__'):
            to_object(attr, value)
        else:
            setattr(my_object, key, value)

obj = MyObject()
data = {'a': 1, 'b': 2}
to_object(obj, data)
Trong Pham
  • 71
  • 2