Home > other >  Best way to create a list of objects?
Best way to create a list of objects?

Time:01-08

food_data is a variable containing JSON data. Using the data, I want to create a list of Food objects, like so

foods = []
for data_row in food_data:
    foods.append(Food(data_row))

This is what my Food class looks like as of right now:

class Food(dict):
    """ by inheriting from dict, Food objects become automatically serializable for JSON formatting """

    def __init__(self, data):
        """ create a serialized food object with desired fields """
        id = data["id"]
        name = data["title"]
        image = data["image"]

        super().__init__(self, id=id, name=name, image=image)

And here is some example data:

[
        {
            "id": 738290,
            "title": "Pasta with Garlic, Scallions, Cauliflower & Breadcrumbs",
            "image": "https://spoonacular.com/recipeImages/716429-312x231.jpg",
        },
        {
            "id": 343245,
            "title": "What to make for dinner tonight?? Bruschetta Style Pork & Pasta",
            "image": "https://spoonacular.com/recipeImages/715538-312x231.jpg",
        }
]

Is there a method I can write for the Food class that will take the data and return a list of different versions of itself?

CodePudding user response:

I would start by not subclassing dict: there is a better way to make an instance of Food serializable.

Next, make Food.__init__ dumb: three arguments, used to set three attributes.

Then, define a class method that is responsible for parsing an arbitrary dict with at least id, title, and image keys to get the values expected by Food.__init__.

Finally, define a method that turns an instance of Food back into a dict (though not necessarily the same dict that from_dict uses; generate one that serializes the way you want).

class Food:
    def __init__(self, id, name, image):
        self.id = id
        self.name = name
        self.image = image

    @classmethod
    def from_dict(cls, d):
        return cls(id=d['id'], name=d['title'], image=d['image'])

    def to_dict(self):
        return dict(id=self.id, name=self.name, image=self.image)

foods = [Food.from_dict(d) for d in food_data]

To make your instance serializable, define a customer encoder that uses your to_dict method,

class FoodEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Food):
            return obj.to_dict()
        return super().default(obj)

This piggy backs on the default encoder; if the immediate object is a Food, default returns a serializable dict. Otherwise, it defers to its parent to try to serialize it.

Then use that class in the call to json.dumps.

print(json.dumps(foods, cls=FoodEncoder))

CodePudding user response:

I think in my case I may have been over-engineering my code. But I received many responses that did help me out in other aspects so I'm going to offer them here:

@Juanpa Use a list comprehension

foods = [Food[data] for data in food_data]

@Chepner - unrelated but useful subclass json.JSONEncoder instead of dict for serializability

@Matthias Create a staticmethod within the class to return a list of objects

@staticmethod
def create_foods(food_data):
    foods = []
    for data_row in food_data:
        foods.append(Food(data_row))
  •  Tags:  
  • Related