2011-07-16 9 views
12

Necesito inicializar todas las ranuras de una instancia con None. ¿Cómo obtengo todos los espacios de una clase derivada?Obtener todos los __slots__ de la clase derivada

Ejemplo (que no funciona):

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" 

que podría utilizar un atributo clase adicional que contiene las ranuras (incluyendo el heredada) para todas las clases, como

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"] 

pero que parece subóptimo.

¡Cualquier comentario es apreciado!

Cheers,

Ene

+1

¿Por qué necesita '__slots__' –

+1

utilizo estas clases para manejar objetos de negocio JSON en el cliente (" tags ": richt client, PyQt, acceso de atributos mediante descriptores, resolución diferida de referencias, validación de tipo). Tengo hasta un millón de esos objetos, por lo que los requisitos de memoria pueden ser un problema (incluso si no tengo datos reales del mundo real ahora; sé lo que estás pensando ... raíz de todo mal ...; -)). Pero también necesito prohibir cualquier creación dinámica de atributos. Esto asegura que no haya atributos 'basura' cuando se vuelven a enviar objetos al servidor. – Knack

Respuesta

11

En primer lugar, es

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

Hacer una lista que contiene todos los elementos contenidos por __slots__ de B o cualquiera de sus clases padre sería:

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

¿Por qué tocar '__mro__' –

+0

Gracias! Eso es ingenioso. ¡Y la primera vez usaré la cadena en mi código! – Knack

+1

Esto no es del todo correcto. Es posible que un atributo aparezca en '__slots__' en varios lugares, p. Ej. en el padre y el niño. Entonces, el iterador de tragamonedas que usted produce puede tener múltiples copias del mismo atributo. Puede hacer algo como 'para cls en b .__ class __.__ mro__: slots.update (getattr (cls," __ slots __ ", []))' donde slots es un objeto como un conjunto. –

7

Quiere iterar a través de cada clase en el 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) 

Se puede ver que esto funciona como se esperaba en la clase derivada:

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

>>> b = B() 

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

Gracias por la respuesta. MRO era la pieza que faltaba. – Knack

Cuestiones relacionadas