Pseudoclases en tiempo de ejecución con Python

Trasteando con mi código, en cierto momento (culpa de las plantillas de Django) me dí cuenta de que perdía una gran cantidad de tiempo declarando clases "auxiliares", que solo iba a usar una vez. Tiempo después, y quizás influenciado por la filosofía del Javascript, encontré una rápida solución: implementar clases a partir de diccionarios.

class DictClass(dict):
def __getattribute__(self,i):
if i[0:2] != "__" and self.__contains__(i):
return self.__getitem__(i)
return dict.__getattribute__(self,i)

Se usa muy fácilmente, en cualquier momento que quieras instanciar una clase, tan sólo tenemos que tratarlo como un diccionario. Pero sus atributos y método serán accesibles como si de una clase se tratase.

aux = DictClass({
"texto": "hola",
"method": lambda x:x+1,
})
aux["texto"] = "hasta la vista"
print(aux.texto)

Además, me he creado otra clase dinámica pero a partir de una lista, cuyos elementos son accesibles como si fuesen atributos (su utilidad se comenta al final).

import re
reitem = re_compile("^item_\d+$")
class ListClass(list):
def __getattribute__(self,i):
if reitem.match(i):
return self.__getitem__( int(i[5:]) )
return list.__getattribute__(self,i)

Y se usaría como una lista, cuyos valores son a su vez atributos.

lista = ListClass([1,2,3])
lista.append(4)
print(lista.item_4)

Tened en cuenta que esta técnica es menos eficiente que declarar las clases "tradicionales" desde el punto de vista del rendimiento, pero permite programar mucho mas rápido, y saltarse ciertas limitaciones del motor de plantillas de Django 1.0, que no permite acceder a las propiedades de los diccionarios y acceder a determinados valores de una lista, si no es a través de bucles.

<p>Valor de propiedad de DictClass: {{ clase.atributo }}</p>
<p>Valor de la primera posición de una lista: {{ lista.item_0 }}</p>

Espero que os haya sido de utilidad, no he descubierto la pólvora, y seguro que hay formas mejores o mas rápidas de ahorrarse tiempo de desarrollo (¿He oido Ruby por algún lado?), pero esto me ha sido muy útil ahorrándome un tercio de dicho tiempo, y por eso lo comparto.

0 comentarios:

Publicar un comentario