2010-04-14 12 views
14

A menudo, me parece que quiero un objeto simple, "volcado" en Python que se comporta como un objeto JavaScript (es decir, se puede acceder a sus miembros con .member o con ['member']).Objeto parecido a JavaScript en la biblioteca estándar de Python?

Por lo general, sólo voy a pegar esto en la parte superior de la .py:

class DumbObject(dict): 
    def __getattr__(self, attr): 
     return self[attr] 
    def __stattr__(self, attr, value): 
     self[attr] = value 

Pero eso es algo escaso, y hay al menos un error con el que la aplicación (aunque no puedo recordar lo que se es).

Entonces, ¿hay algo similar en la biblioteca estándar?

Y, para que conste, simplemente instanciando object no funciona:

 
>>> obj = object() 
>>> obj.airspeed = 42 
Traceback (most recent call last): 
    File "", line 1, in 
AttributeError: 'object' object has no attribute 'airspeed' 

Editar: (Dang, debería haber visto venir esto) ... No se preocupe! No estoy tratando de escribir JavaScript en Python. El lugar que encuentro con mayor frecuencia es el que quiero mientras sigo experimentando: tengo una colección de "cosas" que no me parece correcto poner en un diccionario, pero tampoco me siento bien al tener su propia clase .

+0

Como dije a continuación, está intentando codificar los instintos incorrectos traídos de otro idioma. En Python, escribimos clases incluso cuando estamos "experimentando". Intente - deje de escribir DumbObject, escriba "clase Foo" y vea que no muerde. – moshez

+0

Y, como dije a continuación ... Esa es una idea interesante, simplemente usar, por ejemplo, la clase Foo: velocidad del aire = 42 - No lo había considerado. Sin embargo, tiene el problema de que no se comporta como un diccionario (sí, hay __dict__ ...), lo que hace que la experimentación sea más difícil. –

+0

Parece algo que todos queremos hacer con Python :) http://stackoverflow.com/questions/2466191/set-attributes-from-dictionary-in-python – OscarRyz

Respuesta

5

No existe una "biblioteca estándar" con ese tipo de objeto, pero en ActiveState hay una receta bastante conocida de Alex Martelli, llamada "bunch".

Nota: también hay un paquete disponible en pypi llamado bunch y que debería hacer casi lo mismo, pero no sé nada sobre su implementación y calidad.

+0

Es bueno saberlo, gracias. –

1

yo no soy un gran fan de eso, porque se llega a la "lo que si se define 'llaves'":

foo = DumbObject() 
foo.moshe = 'here' 
foo.keys # --> gives a callable, if you'll call it you'll get ['moshe'] 
foo.keys = 'front-door' 
foo.keys # --> oh look, now it's a string 'front-door' 

es "claves" supone que hay un método definido en el objeto, o es solo casualidad? Si es así, entonces es mejor definir DumbObject como

class DumbObject(object): 
    def __init__(self): 
     self._dict = {} 
    def __getitem__(self, key): 
     return self._dict[key] 
    __getattr__ = __getitem__ 
    # Ditto for set 
def asDictionary(do): 
    return do._dict 

¿Pero por qué lo haces? ¿Estás seguro de que esta es la respuesta correcta? Tal vez deberías estar usando el tipo correcto de objeto?

+0

Ah, no había considerado eso. En ese caso, hay al menos dos errores con la implementación que he usado en el pasado: P –

+0

A menudo me gusta experimentar con datos que realmente no se sienten "correctos" en un diccionario, pero formalizándolos en una clase se siente exagerada. –

+2

Creo que tus problemas son el problema: "formalizarlo en una clase" probablemente no sea excesivo. Se siente como un exceso en idiomas donde las clases no son, como mínimo, una mera "clase Foo (objeto): pase" :-D – moshez

10

Usted puede tratar con attrdict:

class attrdict(dict): 
    def __init__(self, *args, **kwargs): 
     dict.__init__(self, *args, **kwargs) 
     self.__dict__ = self 

a = attrdict(x=1, y=2) 
print a.x, a.y 
print a['x'], a['y'] 

b = attrdict() 
b.x, b.y = 1, 2 
print b.x, b.y 
print b['x'], b['y'] 
+0

Debe completar su ejemplo con, por ejemplo, 'print b ['x']'. Para mostrar que es compatible con ambos métodos de acceso de atributo. –

+0

Buen punto, PreludeAndFugue. Actualicé el código. Gracias. :) – ars

+1

Cambiando '__dict__' ?! ¡Eso es asqueroso! Pero, al mismo tiempo, intrigante ... –

3

Si he entendido bien, desea que un objeto en el que sólo puede volcar atributos. Si estoy en lo correcto, todo lo que tendrías que hacer es crear una clase vacía. Por ejemplo:

>>> class DumpObject: pass 
... 
>>>#example of usage: 
... 
>>> a = DumpObject() 
>>> a.airspeed = 420 
>>> print a.airspeed 
420 

Eso es todo

+0

Close, pero también me gustaría poder tratarlo como un dict (supongo que no estaba del todo claro). –

1

Bueno, por lo que puedo decir (corríjanme si me equivoco) todos los ejemplos que aquí no convierte los diccionarios anidados a un nuevo tipo. Así que hice este ejemplo:

class DotDictionary(dict): 

def __init__(self, init_value): 
    if not isinstance(init_value, dict): 
     raise TypeError('Expected dict, got {}'.format(type(init_value))) 

    self._dict_to_self(init_value) 

def __getattr__(self, name): 
    return self[name] 

def __setattr__(self, name, val): 
    self[name] = val 

def __delattr__(self, name): 
    del self[name] 

def _dict_to_self(self, dct): 
    for key, value in dct.items(): 
     if isinstance(value, dict): 
      value = DotDictionary(value) 
     if isinstance(value, (tuple, list)): 
      for i, _ in enumerate(value): 
       if isinstance(value[i], dict): 
        value[i] = DotDictionary(value[i]) 

     self[key] = value 

ideone

no estoy 100% seguro de que funciona absolutamente correcto, por lo que no garantiza aquí.

También puede que no sea pythonic-way, así que estoy listo para recibir consejos.

Cuestiones relacionadas