Este es un “re-post” en español de este otro articulo que escribí en inglés: Python trick: How to make lazy objects?. Si ya leíste aquel articulo igual te invito a que leas este, compares y compartas.
Esta vez voy a hablar de los “lazy objects”, los he llamado así porque son mas o menos similar a lo que usaba con los “Lazy treeviews” en GTK donde el árbol muestra los expansiones pero no se cargan los nodos hijos hasta que expandes el nodo. Lo que quiero entonces es crear objetos que sirvan para contar, que tengan un tipo de dato, pero que no carguen nada de datos hasta que se necesite.
¿Por que haría esto?, bueno, actualmente estoy trabajando en un programa que muestra una lista de clientes y muestra cuántas cuentas tiene, estas cuentas son algo complejas así como crear el objeto para representarlas. Este objeto es responsable de cargar y guardar datos, y cualquier dato necesario es accesado via “propiedades”.
En mi primer intento, el objeto cargaba con los datos tan pronto como el constructor era llamado, pero a veces nunca accedía a la información en dicho objeto, recuerden, un client puede tener muchas (y me refiero, muchas muchas) cuentas, entonces, ¿por que cargar todos los datos si hay una oportunidad de que nunca voy a usar ese dato?. Bueno, está ahí por qué también hay una oportunidad de que voy a necesitar ese dato.
Entonces, como podría crear un objeto y despues cargar los datos cuando alguien los requiera?. Eso podría ser fácil… tal vez no ?. Una aproximación es hacer uso de las “propiedades” de Python, crear el objeto y cuando alguien necesite un valor de este objeto entonces usar la propiedad para obtener el dato, procesarlo y retornar un valor, una propiedad se puede definir así:
He creadola clase “demo” y la propiedad “some_property”.
Python va a llamar el método get_some_property
permitiéndote hacer el truco. Pero si tienes un objeto con mas y mas propiedades es mejor obtener todos los datos de una vez y solo usar propiedades para regresar un pedazo de el. Podrías llamar a un método en cada propiedad si el contenedor está vacío pero para mi no es lo mejor.
Lo que podemos hacer, es obtener los datos la primera vez que los necesites, pero como sabría que datos/variables son requeridas en mi objeto?.
Bueno, pues las clases de Python tienen ciertos métodos, los llamados “magic methods”, uno de ellos es __getattribute__. Este método te permite manejar cada petición a cualquier propiedad o variable de clase en tu objeto.
Con esto puedes buscar en tu objeto, saber si el contenedor esta vacío y si está vacío entonces llenarlo con datos antes de retornar el valor de la propiedad ?
Digamos que el objeto demo
tiene un diccionario llamado __data
donde almacenaremos la información necesaria, también tenemos propiedades que buscarán por esta información. también tiene una referencia a la capa de almacenamiento.
Presta atención que he usado object.__getattribute__
en lugar de self.property
, si usara self.property
esto llamaría a self.__getattribute__
y esto causaría una excepción de recursión.
Con eso, podemos crear un gran numero de objetos de forma rápida, al mismo tiempo que reducimos el uso de memoria. La paga es que obtener los datos será mas caro si llegaremos a requerir todos los datos de todos los objetos al mismo tiempo.