2016-01-11 15 views
5

Mam klasy GenericProducent podklasa posiada atrybut własnej klasy

class Generic: 
    raw_data = [] 
    objects = dict() 

i konkretne zajęcia

class A(Generic): 
    raw_data = module.somethingA 

class B(Generic): 
    raw_data = module.somethingB 

Chcę zapełnić każdą raw_data na każdym objects dict klasy. Aby, że biegnę:

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 

Jednak to nie działa, ponieważ objects dzielone między A i B i chciałem każdą podklasę Generic mieć własne obiekty.

Jak to zrobić, bez wpisywania objects = dict() na każdej podklasie?

Jestem skłonny powiedzieć, że jest to tradycyjny przypadek, w którym wymagana jest klasa meta (która dodaje objects do każdej nowej klasy); czy tak jest, czy jest prostsza opcja?

Odpowiedz

2

Użyj metaclass lub użyj dekoratora klasy.

Klasa dekorator może po prostu utworzyć atrybut:

def add_objects(cls): 
    cls.objects = {} 
    return cls 

@add_objects 
class A(generic): 
    raw_data = module.somethingA 

To naprawdę nie dodawać nic jednak; po prostu zamieniasz jedną linię (objects = {}) na inną (@add_objects).

może po prostu dodać obiekt w pętli:

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 

lub skopiować go (czytając atrybut może odzyskać atrybutu class rodzic lub bezpośredni atrybut, to nie ma znaczenia tutaj):

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 

lub stworzyć od podstaw słownika:

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),)} 
1

I nie sądzę, metaklasa jest necessa tu jest. Dlaczego po prostu nie kopiować obiektów klasy nadrzędnej przed zapełnianiem każdej podklasy w pętli?

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 

Dodatkowo można modyfikować w użyciu super i/lub deepcopy jeśli chcesz.

Powiązane problemy