DEV Community

Maria Boldyreva
Maria Boldyreva

Posted on • Updated on

Python: update a dict by object

When you have a dict and a non-iterable object you'd like to update the dict from, you can do this:

class A:
    def __init__(self):
        self.fields_names_list = [..attribute names here..]

    def __iter__(self):
        for name in self.fields_names_list:
            yield name, getattr(self, name, None)
Enter fullscreen mode Exit fullscreen mode

And voila, it works:

a = A()
a.foo = 'bar'
b = dict()
b.update(a)
a
# {'foo': 'bar'}
Enter fullscreen mode Exit fullscreen mode

Update: my solution is for legacy code, in general, it's better to use @rhymes solution from the comments.

Discussion (3)

Collapse
rhymes profile image
rhymes • Edited on

Hi Maria, neat trick, you made me think about it and I found a few alternatives if you don't care about whitelisting:

>>> class A:
...     def __init__(self):
...         self.a = 3
...     def __iter__(self):
...         for name in self.__dict__:
...             yield name, getattr(self, name)
...
>>> a = A()
>>>
>>> a.b = 4
>>>
>>> dict(a)
{'a': 3, 'b': 4}

and even easier one without __iter__:

>>> class B:
...     def __init__(self):
...         self.a = 3
...
>>> b = B()
>>> b.c = 5
>>> dict(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'B' object is not iterable
>>> vars(b)
{'a': 3, 'c': 5}
>>> b.__dict__
{'a': 3, 'c': 5}

None is wrong, it depends on how much control you want to have and the last one works also on objects without __iter__. Keep in mind that vars works with the object with iter as well.

Collapse
mxl profile image
Maria Boldyreva Author

Hi. In general case, your solution is better and cleaner than mine. I was so excited to have found the solution (it was a work task) that I forgot to mention, that the object is a huge legacy object and I needed just a few of its attributes and .update(obj) is a legacy line I have no control over. I'll update the post soon, thanks for the comment.

Collapse
rhymes profile image
rhymes

Ahah you see, then your solution is more apt than mine ;-)

I just gave you two other options that are useful in case you cannot modify the source code of the class.