I have an class Generic
class Generic:
    raw_data = []
    objects = dict()
and concrete classes
class A(Generic):
    raw_data = module.somethingA
class B(Generic):
    raw_data = module.somethingB
I want to populate each raw_data onto each objects dict of the class.
To that, I'm running:
for object_type in (A, B):
     for data in object_type.raw_data:
         new_object = object_type(*data)
         object_type.objects[id(new_object)] = new_object
However, this does not work because objects is shared between A and B, and I wanted each subclass of Generic to have their own objects.
How do I achieve this without having to type objects = dict() on every subclass? 
I'm inclined to say that this is a traditional case where a meta class is required (that adds objects to each new class); is this the case, or is there a simpler option?
Either use a metaclass or use a class decorator.
A class decorator could simply create the attribute:
def add_objects(cls):
    cls.objects = {}
    return cls
@add_objects
class A(generic):
    raw_data = module.somethingA
This doesn't really add anything however; you just replace one line (objects = {}) with another (@add_objects).
You could just add the object in your loop:
for object_type in (A, B):
     if 'objects' not in vars(object_type):
         object_type.objects = {}
     for data in object_type.raw_data:
         new_object = object_type(*data)
         object_type.objects[id(new_object)] = new_object
or copy it (reading the attribute may retrieve the parent class attribute or a direct attribute, it doesn't matter here):
for object_type in (A, B):
     object_type.objects = object_type.objects.copy()
     for data in object_type.raw_data:
         new_object = object_type(*data)
         object_type.objects[id(new_object)] = new_object
or create the dictionary from scratch:
for object_type in (A, B):
     object_type.object = {
         id(new_object): new_object
         for data in object_type.raw_data
         for new_object in (object_type(*data),)}
                        I don't think a metaclass is necessary here. Why not just copy the parent class objects before populating each subclass in your loop?
for object_type in (A, B):
     # copy Generic.objects onto object_type.objects here
     object_type.objects = Generic.objects.copy()
     for data in object_type.raw_data:
         new_object = object_type(*data)
         object_type.objects[id(new_object)] = new_object
Additionally you can modify to use super and/or deepcopy if you want.  
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With