2011-07-16 10 views
12

Muszę zainicjować wszystkie gniazda instancji za pomocą Brak. Jak uzyskać wszystkie gniazda klasy pochodnej?Uzyskaj wszystkie __slots__ z klasy pochodnej

Przykład (który nie działa):

class A(object): 
    __slots__ = "a" 

    def __init__(self): 
     # this does not work for inherited classes 
     for slot in type(self).__slots__: 
      setattr(self, slot, None) 

class B(A): 
    __slots__ = "b" 

mogę użyć dodatkowego atrybutu class, która posiada otwory (w tym dziedziczone) dla wszystkich klas, takich jak

class A(object): 
    __slots__ = "a" 
    all_slots = "a" 

    def __init__(self): 
     # this does not work for inherited classes 
     for slot in type(self).all_slots: 
      setattr(self, slot, None) 

class B(A): 
    __slots__ = "b" 
    all_slots = ["a", "b"] 

ale wydaje nieoptymalny.

Wszelkie uwagi są mile widziane!

Cheers,

Jan

+1

dlaczego trzeba '__slots__' –

+1

używam tych klas do obsługi elementów biznesowych JSON po stronie klienta (” tags ": richt client, PyQt, dostęp do atrybutów za pomocą deskryptorów, leniwy rozwiązywanie referencji, sprawdzanie poprawności typów). Mam do miliona takich obiektów, więc wymagania dotyczące pamięci mogą być problemem (nawet jeśli nie mam teraz prawdziwych danych z tego świata - wiem, co myślisz ... źródło wszelkiego zła ...;)). Ale muszę również zabronić tworzenia dynamicznych atrybutów. Dzięki temu nie ma atrybutów "śmieci" podczas wysyłania nowo utworzonych obiektów z powrotem na serwer. – Knack

Odpowiedz

11

Przede wszystkim, to

class A(object): 
    __slots__ = ('a',) 
class B(A): 
    __slots__ = ('b',) 

Sporządzenie listy, która zawiera wszystkie elementy zawarte przez __slots__ B lub któregokolwiek z jej klas nadrzędnych byłoby:

from itertools import chain 
slots = chain.from_iterable(getattr(cls, '__slots__', []) for cls in B.__mro__) 
+0

Dlaczego dotykać '__mro__' –

+0

Dzięki! To fajne. I po raz pierwszy użyję łańcucha w moim kodzie! – Knack

+1

To nie jest w porządku. Atrybut może się pojawiać w '__slots__' w wielu miejscach, np. w rodzicu i dziecku. Tak utworzony iterator slotów może mieć wiele kopii tego samego atrybutu. Może zrobić coś takiego jak "cls in b .__ class __.__ mro__: slots.update (getattr (cls," __ slots __ ", []))' gdzie sloty to jakiś obiekt podobny do zestawu. –

7

Chcesz powtórzyć każdą klasę w MRO:

class A(object): 
    __slots__ = ('x', 'y') 
    def __init__(self): 
     for slots in [getattr(cls, '__slots__', []) for cls in type(self).__mro__]: 
      for attr in slots: 
       setattr(self, attr, None) 

Widać, że to działa zgodnie z oczekiwaniami w klasie pochodnej:

class B(A): 
    __slots__ = ('z',) 

>>> b = B() 

>>> b.x, b.y, b.z 
<<< (None, None, None) 
+0

Dzięki za odpowiedź. MRO było brakującym elementem. – Knack

Powiązane problemy