¿Cómo borrar datos de instancia sin setattr?

Quería hacer una clase transitable (por base de datos, archivo único o simplemente como cadena) en python. Escribo esto (abreviado):

from json import JSONDecoder, JSONEncoder
def json_decode(object): return JSONDecoder().decode(object)
def json_encode(object): return JSONEncoder().encode(object)

class Storage:
__separator__ = 'ANY OF ANYS'
__keys__ = []
__vals__ = []
__slots__ = ('__keys__', '__vals__', '__separator__')

def __getattr__(self, key):
    try:
        return self.__vals__[self.__keys__.index(key)]
    except IndexError:
        raise AttributeError

def __setattr__(self, key, val):
    self.__keys__.append(key)
    self.__vals__.append(val)

def store(self):
    return (json_encode(self.__keys__) + self.__separator__ +
            json_encode(self.__vals__))

def restore(self, stored):
    stored = stored.split(self.__separator__)
    for (key, val) in zip(json_decode(stored[0]), json_decode(stored[1])):
        setattr(self, key, val)

Y sí, eso funciona, pero... Cuando hago más instancias, todas son como singleton.

Entonces, cómo establecer el atributo a la instancia sin _setattr_?

PD. Tengo una idea - hacer en establecer/getattr un pase para claves/valores, pero hará un lío.

preguntado el 12 de junio de 12 a las 21:06

2 Respuestas

tu __separator__, __keys__, __vals__ y __slots__ son atributos del objeto "Almacenamiento" (objeto de clase). No sé si es exactamente lo mismo, pero lo llamaría variables estáticas de la clase.

Si desea tener valores diferentes para cada instancia de Almacenamiento, defina cada una de estas variables en su __init__ función:

class Storage(object):
    __slots__ = ('__keys__', '__vals__', '__separator__')
    def __init__(self):
        super(Storage, self).__setattr__('__separator__', "ANY OF ANYS")
        super(Storage, self).__setattr__('__keys__', [])
        super(Storage, self).__setattr__('__vals__', [])

    def __getattr__(self, key):
        try:
            vals = getattr(self, '__vals__')
            keys = getattr(self, '__keys__')
            return vals[keys.index(key)]
        except IndexError:
            raise AttributeError

    def __setattr__(self, key, val):
        vals = getattr(self, '__vals__')
        keys = getattr(self, '__keys__')
        vals.append(val)
        keys.append(key)

editado para que getattr y setattr funcionen

Tengo ese problema hace 2 días. No sé si ese es exactamente tu problema, pero dijiste que "es como si tuviera un singleton".

Respondido el 12 de junio de 12 a las 22:06

ranuras son para guardar memoria (google it) self.xxx será analizado por setattr, así que eso no es lo que quiero. - Radoslaw Miernik

entonces vete __slots__ como era antes. Pero si no establece un diferente [] a ambos __keys__ y __vals__ en cada instancia (como sugerí), compartirá la misma lista en todas sus instancias: Alberto Ferras

Lo intenté. __getattr__. Cuando quiero self.__key/vals__, obtuve un error profundo de recurrencia máxima - __getattr__ operar en __key/vals__. - Radoslaw Miernik

eso fue porque en __init__ estaba usando tu nuevo obtener función, actualicé el código (y probé, funciona para mí con múltiples instancias). Es un poco complicado pero hace el trabajo. - Alberto Ferras

ahora entiendo tu problema :) Si no es lo que querías (porque uso el objeto de clase para heredar el obtener) entonces está bien, esperaré aquí para ver la solución - Alberto Ferras

Podrías hacer tu Storage clase una subclase de una clase base especial como esta:

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if '_inst_' not in vars(cls):
            cls._inst = type.__new__(cls, *args, *kwargs)
        return cls._inst

class Storage(Singleton):
    ....

Siempre y cuando no anules __new__() en su subclase, todas las llamadas posteriores para crear nuevas instancias después de la primera devolverán la que se creó primero.

Respondido el 12 de junio de 12 a las 22:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.