{"id":5794,"date":"2019-08-07T09:48:40","date_gmt":"2019-08-07T14:48:40","guid":{"rendered":"https:\/\/islascruz.org\/blog\/?p=5794"},"modified":"2019-08-07T11:37:10","modified_gmt":"2019-08-07T16:37:10","slug":"truco-de-python-como-crear-objetos-flojos-lazy-objects","status":"publish","type":"post","link":"https:\/\/islascruz.org\/blog\/2019\/08\/07\/truco-de-python-como-crear-objetos-flojos-lazy-objects\/","title":{"rendered":"Truco de Python, como crear objetos &#8220;flojos&#8221; (Lazy objects)"},"content":{"rendered":"\n<p>Este es un &#8220;re-post&#8221; en espa\u00f1ol de este otro articulo que escrib\u00ed en ingl\u00e9s: <a href=\"https:\/\/islascruz.org\/blog\/2015\/10\/19\/python-trick-how-to-make-lazy-objects\/\">Python trick: How to make lazy objects?<\/a>. Si ya le\u00edste aquel articulo igual te invito a que leas este, compares y compartas.<\/p>\n\n\n\n<p>Esta vez voy a hablar de los &#8220;lazy objects&#8221;, los he llamado as\u00ed porque son mas o menos similar a lo que usaba con los &#8220;Lazy treeviews&#8221; en GTK donde el \u00e1rbol 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.<\/p>\n\n\n\n<p>\u00bfPor que har\u00eda esto?, bueno, actualmente estoy trabajando en un programa que muestra una lista de clientes y muestra cu\u00e1ntas cuentas tiene, estas cuentas son algo complejas as\u00ed como crear el objeto para representarlas. Este objeto es responsable de cargar y guardar datos, y cualquier dato necesario es accesado via &#8220;propiedades&#8221;.<\/p>\n\n\n\n<p>En mi primer intento, el objeto cargaba con los datos tan pronto como el constructor era llamado, pero a veces nunca acced\u00eda a la informaci\u00f3n en dicho objeto, recuerden, un client puede tener muchas (y me refiero, muchas muchas) cuentas, entonces, \u00bfpor que cargar todos los datos si hay una oportunidad de que nunca voy a usar ese dato?. Bueno, est\u00e1 ah\u00ed por qu\u00e9 tambi\u00e9n hay una oportunidad de que voy a necesitar ese dato.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"740\" height=\"156\" src=\"https:\/\/islascruz.org\/blog\/wp-content\/uploads\/2019\/08\/Screen-Shot-2017-08-06-at-2.01.30-PM.png\" alt=\"\" class=\"wp-image-5795\" srcset=\"https:\/\/islascruz.org\/blog\/wp-content\/uploads\/2019\/08\/Screen-Shot-2017-08-06-at-2.01.30-PM.png 740w, https:\/\/islascruz.org\/blog\/wp-content\/uploads\/2019\/08\/Screen-Shot-2017-08-06-at-2.01.30-PM-300x63.png 300w\" sizes=\"auto, (max-width: 740px) 100vw, 740px\" \/><\/figure>\n\n\n\n<p>Entonces, como podr\u00eda crear un objeto y despues cargar los datos cuando alguien los requiera?. Eso podr\u00eda ser f\u00e1cil&#8230; tal vez no ?. Una aproximaci\u00f3n es hacer uso de las &#8220;propiedades&#8221; 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\u00ed:<\/p>\n\n\n\n<p>He creadola clase &#8220;demo&#8221; y la propiedad &#8220;some_property&#8221;.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"740\" height=\"34\" src=\"https:\/\/islascruz.org\/blog\/wp-content\/uploads\/2019\/08\/Screen-Shot-2017-08-06-at-2.01.42-PM.png\" alt=\"\" class=\"wp-image-5796\" srcset=\"https:\/\/islascruz.org\/blog\/wp-content\/uploads\/2019\/08\/Screen-Shot-2017-08-06-at-2.01.42-PM.png 740w, https:\/\/islascruz.org\/blog\/wp-content\/uploads\/2019\/08\/Screen-Shot-2017-08-06-at-2.01.42-PM-300x14.png 300w\" sizes=\"auto, (max-width: 740px) 100vw, 740px\" \/><\/figure>\n\n\n\n<p>Python va a llamar el m\u00e9todo <code>get_some_property<\/code> permiti\u00e9ndote 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\u00edas llamar a un m\u00e9todo en cada propiedad si el contenedor est\u00e1 vac\u00edo pero para mi no es lo mejor.<\/p>\n\n\n\n<p>Lo que podemos hacer, es obtener los datos la primera vez que los necesites, pero como sabr\u00eda que datos\/variables son requeridas en mi objeto?.<\/p>\n\n\n\n<p>Bueno, pues las clases de Python tienen ciertos m\u00e9todos, los llamados &#8220;magic methods&#8221;, uno de ellos es <a href=\"http:\/\/docs.python.org\/reference\/datamodel.html#object.__getattribute__\" target=\"_blank\" rel=\"noopener\">__getattribute__<\/a>. Este m\u00e9todo te permite manejar cada petici\u00f3n a cualquier propiedad o variable de clase en tu objeto.<\/p>\n\n\n\n<p>Con esto puedes buscar en tu objeto, saber si el contenedor esta vac\u00edo y si est\u00e1 vac\u00edo entonces llenarlo con datos antes de retornar el valor de la propiedad ?<\/p>\n\n\n\n<p>Digamos que el objeto <code>demo<\/code> tiene un diccionario llamado <code>__data<\/code> donde almacenaremos la informaci\u00f3n necesaria, tambi\u00e9n tenemos propiedades que buscar\u00e1n por esta informaci\u00f3n. tambi\u00e9n tiene una referencia a la capa de almacenamiento. <\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"739\" height=\"287\" src=\"https:\/\/islascruz.org\/blog\/wp-content\/uploads\/2019\/08\/Screen-Shot-2017-08-06-at-2.01.49-PM.png\" alt=\"\" class=\"wp-image-5797\" srcset=\"https:\/\/islascruz.org\/blog\/wp-content\/uploads\/2019\/08\/Screen-Shot-2017-08-06-at-2.01.49-PM.png 739w, https:\/\/islascruz.org\/blog\/wp-content\/uploads\/2019\/08\/Screen-Shot-2017-08-06-at-2.01.49-PM-300x117.png 300w\" sizes=\"auto, (max-width: 739px) 100vw, 739px\" \/><\/figure>\n\n\n\n<p>Presta atenci\u00f3n que he usado <code>object.__getattribute__<\/code> en lugar de <code>self.property<\/code>, si usara <code>self.property<\/code>esto llamar\u00eda a <code>self.__getattribute__<\/code> y esto causar\u00eda una excepci\u00f3n de recursi\u00f3n.<\/p>\n\n\n\n<p>Con eso, podemos crear un gran numero de objetos de forma r\u00e1pida, al mismo tiempo que reducimos el uso de memoria. La paga es que obtener los datos ser\u00e1 mas caro si llegaremos a requerir todos los datos de todos los objetos al mismo tiempo.<\/p>\n\n\n\n<p><\/p>\n<div class=\"pvc_clear\"><\/div><p id=\"pvc_stats_5794\" class=\"pvc_stats all  \" data-element-id=\"5794\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/islascruz.org\/blog\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p><div class=\"pvc_clear\"><\/div>","protected":false},"excerpt":{"rendered":"<p>Este es un &#8220;re-post&#8221; en espa\u00f1ol de este otro articulo que escrib\u00ed en ingl\u00e9s: Python trick: How to make lazy objects?. Si ya le\u00edste aquel articulo igual te invito a que leas este, compares y compartas. Esta vez voy a hablar de los &#8220;lazy objects&#8221;, los he llamado as\u00ed porque son mas o menos similar [&hellip;]<\/p>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_5794\" class=\"pvc_stats all  \" data-element-id=\"5794\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/islascruz.org\/blog\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"author":1,"featured_media":5797,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14,15,239],"tags":[],"class_list":["post-5794","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-programming","category-python","category-tips-and-tricks"],"a3_pvc":{"activated":true,"total_views":12677,"today_views":1},"brizy_media":[],"_links":{"self":[{"href":"https:\/\/islascruz.org\/blog\/wp-json\/wp\/v2\/posts\/5794","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/islascruz.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/islascruz.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/islascruz.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/islascruz.org\/blog\/wp-json\/wp\/v2\/comments?post=5794"}],"version-history":[{"count":1,"href":"https:\/\/islascruz.org\/blog\/wp-json\/wp\/v2\/posts\/5794\/revisions"}],"predecessor-version":[{"id":5798,"href":"https:\/\/islascruz.org\/blog\/wp-json\/wp\/v2\/posts\/5794\/revisions\/5798"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/islascruz.org\/blog\/wp-json\/wp\/v2\/media\/5797"}],"wp:attachment":[{"href":"https:\/\/islascruz.org\/blog\/wp-json\/wp\/v2\/media?parent=5794"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/islascruz.org\/blog\/wp-json\/wp\/v2\/categories?post=5794"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/islascruz.org\/blog\/wp-json\/wp\/v2\/tags?post=5794"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}