1

Giving the whole context for this basic question is a bit overkill, but it may help others as it seems domain driven design (DDD) is gaining some traction in Python.

I am trying to serialize a collection of objects. For that, I use a to_dict function in the class and then access it in a dictionary comprehension:

dict_users = {"users": [user.to_dict() for user in ls_users]}

How can I extend the dictionary output by user.to_dict() with an additional attribute from the same user inside the loop, without modifying to_dict() ?

Example:

from dataclasses import dataclass

@dataclass
class User:
    """
    the `id` is added here for convenience
    in reality, it is defined in the SQLAlchemy ORM layer
    """
    id: int
    name: str
    age: int

    def to_dict(self):
        data = {
            "name": self.name,
            "age": self.age,
        }
        return data

u1 = User(1, "Jane", 32)
u2 = User(2, "John", 29)
u3 = User(3, "Robert", 45)

ls_users = [u1, u2, u3]


# this works but do not return the id (expected)
dict_users = {"users": [user.to_dict() for user in ls_users]}
print(dict_users)

# this does not work
dict_users = {"users": [user.to_dict().update({"id": user.id}) for user in ls_users]}
print(dict_users)
# {"users": [None, None, None]}
Lionel Hamayon
  • 1,240
  • 15
  • 25
  • 1
    Does this answer your question? [How do I merge two dictionaries in a single expression (taking union of dictionaries)?](https://stackoverflow.com/questions/38987/how-do-i-merge-two-dictionaries-in-a-single-expression-taking-union-of-dictiona) – Homan Sep 28 '21 at 10:30
  • Thanks for the link, I did not know about the pipe syntax {"id": user.id} | user.to_dict() - for Python 3.9 – Lionel Hamayon Sep 28 '21 at 10:41

1 Answers1

1

You could use dictionary unpacking:

dict_users = {"users": [{"id": user.id, **user.to_dict()} for user in ls_users]}
print(dict_users)

Output

{'users': [{'id': 1, 'name': 'Jane', 'age': 32}, {'id': 2, 'name': 'John', 'age': 29}, {'id': 3, 'name': 'Robert', 'age': 45}]}
Dani Mesejo
  • 61,499
  • 6
  • 49
  • 76