{"id":5387,"date":"2012-09-02T13:56:44","date_gmt":"2012-09-02T11:56:44","guid":{"rendered":"http:\/\/elclubdelautodidacta.es\/wp\/?p=5387"},"modified":"2012-09-02T13:56:44","modified_gmt":"2012-09-02T11:56:44","slug":"python-el-sagrado-misterio-de-la-inmutabilidad","status":"publish","type":"post","link":"http:\/\/elclubdelautodidacta.es\/wp\/2012\/09\/python-el-sagrado-misterio-de-la-inmutabilidad\/","title":{"rendered":"Python: El sagrado misterio de la inmutabilidad"},"content":{"rendered":"<p><a href=\"http:\/\/elclubdelautodidacta.es\/wp\/wp-content\/uploads\/2011\/12\/ECDA-python.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/elclubdelautodidacta.es\/wp\/wp-content\/uploads\/2011\/12\/ECDA-python.png\" alt=\"\" title=\"ECDA-python\" width=\"181\" height=\"242\" class=\"alignleft size-full wp-image-2584\" \/><\/a><em><strong>Objetivo:<\/strong> comprender los conceptos cr\u00edticos de mutabilidad, inmutabilidad y referencia en Python.<\/em><\/p>\n<p>Est\u00e1s ante un art\u00edculo <strong>esencial<\/strong> en tu formaci\u00f3n como programador en <em>Python<\/em>. Te llevar\u00e1 s\u00f3lo cinco minutos leerlo, pero puede dar luz sobre conceptos que no resultan ni mucho menos obvios cuando se comienza con <em>Python<\/em>, particularmente si procedes de otros lenguajes de programaci\u00f3n.<\/p>\n<p>Por lo general, cuando empezamos a estudiar un lenguaje de programaci\u00f3n, se nos cuenta que existen distintos <em>tipos de datos<\/em>, tales como <em>num\u00e9ricos<\/em>, <em>strings<\/em>, etc.<\/p>\n<p>En <em>Python<\/em> se nos ense\u00f1a algo m\u00e1s: determinados tipos son <strong>inmutables<\/strong> y otros <strong>mutables<\/strong>. Los <em>n\u00fameros<\/em>, los <em>strings<\/em> y las <em>tuplas<\/em> son <em>inmutables<\/em>. Por el contrario, las <em>listas<\/em> son <em>mutables<\/em>.<\/p>\n<p>Ah\u00ed ya empiezan a sacudirnos algo; pero nuestro cerebro, al que no le gustan las dudas, intenta buscar una respuesta coherente para no quedarse atascado y seguir avanzando. Claro: los <em>n\u00fameros<\/em>, los <em>strings<\/em> y las <em>tuplas<\/em> <strong>no se pueden modificar<\/strong>, mientras que las <em>listas<\/em> <strong>s\u00ed<\/strong>.<\/p>\n<p>Bueno, bueno, un momento:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; a = 5\n&gt;&gt;&gt; b = &#039;pradera&#039;<\/code><\/pre><\/p>\n<p>La variable a <em>contiene<\/em> un <em>n\u00famero<\/em>; la variable b <em>contiene<\/em> un <em>string<\/em>. Hemos dicho que los <em>n\u00fameros<\/em> y los <em>strings<\/em> son <em>inmutables<\/em>. \u00bfSignifica eso que no podemos modificar ni <em>a<\/em> ni <em>b<\/em>?<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; a = 6\n&gt;&gt;&gt; b = &#039;casa&#039;\n&gt;&gt;&gt; a\n6\n&gt;&gt;&gt; b\n&#039;casa&#039;<\/code><\/pre><\/p>\n<p>Pues <strong>s\u00ed, se pueden modificar<\/strong> (de no ser as\u00ed Python tendr\u00eda un serio problema), por lo que eso de la <em>inmutabilidad<\/em> debe de significar algo diferente. Decir que un <em>tupla<\/em> es <em>inmutable<\/em>, pero una <em>lista<\/em> no, \u00bfsignificar\u00e1 acaso que \u00e9sta tiene cosquillas pero la otra no?<\/p>\n<p>M\u00e1s adelante cuando estudiamos las <em>listas<\/em> y las <em>tuplas<\/em> creemos haber comprendido, al fin, el misterio.<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; lista = [1, 2, 3, 4]\n&gt;&gt;&gt; lista[0] = 5\n&gt;&gt;&gt; lista\n[5, 2, 3, 4]<\/code><\/pre><\/p>\n<p>Bien: las <em>listas<\/em>, <em>mutables<\/em>, se pueden modificar.<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; tupla = (1, 2, 3, 4)\n&gt;&gt;&gt; tupla[0] = 5\nTraceback (most recent call last):\n&nbsp;&nbsp;File &quot;&lt;pyshell#55&gt;&quot;, line 1, in &lt;module&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;tupla[0] = 5\nTypeError: &#039;tuple&#039; object does not support item assignment<\/code><\/pre><\/p>\n<p>En cambio, las <em>tuplas<\/em>, <em>inmutables<\/em>, no, como podemos comprobar.<\/p>\n<p>Aprendemos tambi\u00e9n que los <em>strings<\/em> tambi\u00e9n son <strong>secuencias<\/strong>, como las <em>listas<\/em> y las <em>tuplas<\/em> y, como tales, <strong>podemos acceder a sus caracteres individuales<\/strong>:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; serie = &#039;la casa de la pradera&#039;\n&gt;&gt;&gt; serie[3]\n&#039;c&#039;<\/code><\/pre><\/p>\n<p>Pero <strong>no podemos modificarlos<\/strong>:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; serie[3] = &#039;k&#039;\nTraceback (most recent call last):\n&nbsp;&nbsp;File &quot;&lt;pyshell#60&gt;&quot;, line 1, in &lt;module&gt;\n&nbsp;&nbsp;&nbsp;&nbsp;serie[3] = &#039;k&#039;\nTypeError: &#039;str&#039; object does not support item assignment<\/code><\/pre><\/p>\n<p>Un error semejante al que recibimos al tratar de modificar una <em>tupla<\/em>. Esto hace que cuadre todo: los <em>strings<\/em> son <em>inmutables<\/em>, tambi\u00e9n.<\/p>\n<p>Pero \u00bfcuadra realmente todo? Parece que s\u00ed, aunque no aparenta tener mucho sentido pr\u00e1ctico eso de la <em>inmutabilidad<\/em> de los <em>n\u00fameros<\/em>.<\/p>\n<p>Tarde o temprano, cualquier estudiante de <em>Python<\/em> que ya ha programado en otros lenguajes se enfrenta al siguiente misterio.<\/p>\n<p>Observ\u00e9moslo muy despacio:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; x = 5\n&gt;&gt;&gt; y = x<\/code><\/pre><\/p>\n<p>Pregunta: \u00bfcu\u00e1nto crees que vale <em>y<\/em>?<\/p>\n<p>En efecto, 5:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; y\n5<\/code><\/pre><\/p>\n<p>Modifiquemos ahora el valor de <em>x<\/em>:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; x = 6\n<\/code><\/pre><\/p>\n<p>\u00bfCu\u00e1nto crees que valdr\u00e1 ahora <em>y<\/em>?<\/p>\n<p>Vamos a ver, no me asustes: <em>x<\/em> e <em>y<\/em> son dos variables diferentes, cada una con su propio contenido; por lo tanto <em>y<\/em> tiene que seguir valiendo 5, aunque hayas modificado <em>x<\/em>, \u00bfno?<\/p>\n<p>En efecto, as\u00ed es:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; y\n5<\/code><\/pre><\/p>\n<p>Veamos otro ejemplo. Ahora <em>x<\/em> es una <em>lista<\/em>:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; x = [1, 2, 3, 4]\n&gt;&gt;&gt; y = x\n&gt;&gt;&gt; y\n[1, 2, 3, 4]<\/code><\/pre><\/p>\n<p>Voy a modificar el valor de <em>x<\/em>:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; x[0] = 5\n&gt;&gt;&gt; x\n[5, 2, 3, 4]<\/code><\/pre><\/p>\n<p>\u00bfCu\u00e1nto crees que valdr\u00e1 ahora <em>y<\/em>?<\/p>\n<p>Por la l\u00f3gica anterior, <em>x<\/em> e <em>y<\/em> son dos variables diferentes, cada una con su propio contenido, por lo que cabr\u00eda esperar que el valor de <em>y<\/em> fuera [1, 2, 3, 4].<\/p>\n<p>Pero no es as\u00ed:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; y\n[5, 2, 3, 4]<\/code><\/pre><\/p>\n<p>Esto rompe completamente nuestros esquemas. Si somos programadores en otros lenguajes una <strong>alarma<\/strong> nos sacude inmediatamente.<\/p>\n<p>\u00bfPor qu\u00e9 al modificar <em>x<\/em> ha cambiado <em>y<\/em> tambi\u00e9n?<\/p>\n<p>De acuerdo: los n\u00fameros son <em>inmutables<\/em>, pero las <em>listas<\/em> no. \u00bfPero qu\u00e9 tiene que ver esto con el hecho de que se haya modificado el valor de <em>y<\/em>?<\/p>\n<p>Para resolver el misterio hace falta un una nueva <strong>pieza clave<\/strong>: el concepto de <strong>referencia<\/strong>.<\/p>\n<p>Veamos lo que est\u00e1 sucediendo realmente entre bastidores:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; x = 5\n<\/code><\/pre><\/p>\n<p>En <em>Python<\/em>, <strong>todo son objetos<\/strong>. Se acaba de crear uno nuevo: un <em>n\u00famero<\/em> de valor 5.<\/p>\n<p>Este objeto, que reside en alg\u00fan lugar de la memoria, posee un identificador \u00fanico que lo diferencia del resto de los objetos. Piensa en \u00e9l como si fuera su <em>DNI<\/em> (es, en realidad, la direcci\u00f3n de memoria en la que reside el objeto).<\/p>\n<p>Para conocer ese identificador, <em>Python<\/em> dispone de la funci\u00f3n <strong>id()<\/strong>:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; id(5)\n137396064\n<\/code><\/pre><\/p>\n<p>Y ahora el concepto <strong>cr\u00edtico<\/strong>: la variable <em>x<\/em> no es m\u00e1s que una <strong>referencia<\/strong> a ese objeto. A efectos pr\u00e1cticos, es como si se tratara de un <em>puntero<\/em> (empleando conceptos de otros lenguajes) a ese objeto. <strong>No contiene su valor, sino una referencia a \u00e9l<\/strong>.<\/p>\n<p>La funci\u00f3n <strong>id()<\/strong>, aplicada a una variable, nos devuelve el <em>id<\/em> del objeto al que referencia, por lo que obtenemos el mismo valor que antes:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; id(x)\n137396064<\/code><\/pre><\/p>\n<p>Proseguimos; asignamos a la variable <em>y<\/em> el valor de<em> x<\/em>:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; y = x\n<\/code><\/pre><\/p>\n<p>Observa ahora cuidadosamente qu\u00e9 pasa al preguntar por el <em>id<\/em> del objeto al que referencia <em>y<\/em>:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; id(y)\n137396064<\/code><\/pre><\/p>\n<p>Exactamente <strong>el mismo<\/strong> al que referencia <em>x<\/em>. Tanto <em>x<\/em> como <em>y<\/em> apuntan al mismo objeto.<\/p>\n<p>Este es un concepto radicalmente distinto al de las variables en otros lenguajes, en los que el contenido de <em>x<\/em> y de <em>y<\/em> estar\u00eda en diferentes direcciones de memoria.<\/p>\n<p>A continuaci\u00f3n, modificamos <em>x<\/em>:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; x = 6\n&gt;&gt;&gt; id(x)\n137396080<\/code><\/pre><\/p>\n<p>Se ha creado un nuevo objeto, de valor 6, y ahora <em>x<\/em> apunta a ese valor. Esto tambi\u00e9n es muy diferente a lo que suceder\u00eda en otros lenguajes: la variable <em>x<\/em> seguir\u00eda en la misma direcci\u00f3n de memoria, habiendo modificado \u00fanicamente su contenido.<\/p>\n<p>Fij\u00e9monos que, como es de esperar, <em>y<\/em> sigue apuntando al objeto primero:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; id(y)\n137396064\n&gt;&gt;&gt; y\n5<\/code><\/pre><\/p>\n<p>Analicemos ahora qu\u00e9 sucede en el caso de las listas:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; x = [1, 2, 3, 4]\n&gt;&gt;&gt; y = x\n&gt;&gt;&gt; id(x)\n170964396\n&gt;&gt;&gt; id(y)\n170964396<\/code><\/pre><\/p>\n<p>De momento, todo es exactamente igual que antes: <strong>se ha creado un \u00fanico objeto<\/strong>, la lista <code class=\"preserve-code-formatting\">[1, 2, 3, 4]<\/code>, que est\u00e1 referenciado por dos variables,<em> x<\/em> e <em>y<\/em>.<\/p>\n<p>Si ahora <strong>modificamos directamente el objeto<\/strong> (al ser mutable, podemos hacerlo):<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; x[0] = 5\n&gt;&gt;&gt; id(x)\n170964396\n&gt;&gt;&gt; id(y)\n170964396<\/code><\/pre><\/p>\n<p>comprobamos que tanto <em>x<\/em> como <em>y<\/em> siguen siendo referencias al <strong>mismo objeto<\/strong>. <\/p>\n<p>Por lo tanto <em>y<\/em> tiene el mismo valor que <em>x<\/em>:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; y\n[5, 2, 3, 4]<\/code><\/pre><\/p>\n<p>En el ejemplo anterior, cuando hicimos <code class=\"preserve-code-formatting\">x = 6<\/code>, se cre\u00f3 un nuevo objeto. En el caso de la lista, hemos modificado <strong>in situ<\/strong> el <strong>propio<\/strong> objeto, aprovech\u00e1ndonos de su <em>mutabilidad<\/em>. Es como si un cirujano hubiese realizado una operaci\u00f3n sobre el objeto.<\/p>\n<p>La situaci\u00f3n habr\u00eda sido muy distinta si hubi\u00e9ramos hecho esto otro:<\/p>\n<p><pre><code class=\"preserve-code-formatting\">&gt;&gt;&gt; x = [1, 2, 3, 4]\n&gt;&gt;&gt; y = x\n&gt;&gt;&gt; x = [5, 2, 3, 4]\n&gt;&gt;&gt; y\n[1, 2, 3, 4]\n&gt;&gt;&gt; id(x)\n170489580\n&gt;&gt;&gt; id(y)\n170791756<\/code><\/pre><\/p>\n<p>F\u00edjate en la importante diferencia: al hacer <code class=\"preserve-code-formatting\">x = [5, 2, 3, 4]<\/code> hemos creado un objeto diferente, de modo que <em>x<\/em> e <em>y<\/em> apuntan a objetos distintos y por eso ahora sus valores difieren. En el caso anterior, al hacer <code class=\"preserve-code-formatting\">x[0] = 5<\/code> modificamos <strong>directamente<\/strong> el mismo objeto y<strong> no se cre\u00f3 otro nuevo<\/strong>.<\/p>\n<p>Espero que todo resulte m\u00e1s claro ahora y entiendas la diferencia esencial que hay en lo que respecta al concepto de variable respecto a otros lenguajes de programaci\u00f3n. Si es as\u00ed, felic\u00edtate, pues habr\u00e1s cambiado de nivel en tu proceso de aprendizaje de <em>Python<\/em>.<\/p>\n<p><strong><span style=\"color: #808080;\">Javier Montero Gabarr\u00f3<\/span><\/strong><\/p>\n<hr \/>\n<p>http:\/\/elclubdelautodidacta.es\/wp\/2012\/09\/python-el-sagrado-misterio-de-la-inmutabilidad\/<\/p>\n<hr \/>\n<p>El texto de este art\u00edculo se encuentra sometido a una licencia <em>Creative Commons<\/em> del tipo <strong>CC-BY-NC-ND<\/strong> (reconocimiento, no comercial, sin obra derivada, 3.0 unported)<\/p>\n<hr \/>\n<p><em>El Club del Autodidacta<\/em><\/p>\n<hr \/>\n<p>Consulta el \u00edndice completo de art\u00edculos relacionados con <a href=\"http:\/\/elclubdelautodidacta.es\/wp\/indice-python\/\">Python<\/a>.<\/p>\n<div class=\"SPOSTARBUST-Related-Posts\"><H3>Tal vez te interese...<\/H3><ul class=\"entry-meta\"><li class=\"SPOSTARBUST-Related-Post\"><a title=\"Python &#8211; Buscando a Wally.txt\" href=\"http:\/\/elclubdelautodidacta.es\/wp\/2016\/02\/python-buscando-a-wally-txt\/\" rel=\"bookmark\">Python &#8211; Buscando a Wally.txt<\/a><\/li>\n<li class=\"SPOSTARBUST-Related-Post\"><a title=\"Python &#8211; Troceando desde el lado izquierdo\" href=\"http:\/\/elclubdelautodidacta.es\/wp\/2015\/12\/python-troceando-desde-el-lado-izquierdo\/\" rel=\"bookmark\">Python &#8211; Troceando desde el lado izquierdo<\/a><\/li>\n<li class=\"SPOSTARBUST-Related-Post\"><a title=\"Comparando objetos en Python\" href=\"http:\/\/elclubdelautodidacta.es\/wp\/2015\/06\/comparando-objetos-en-python\/\" rel=\"bookmark\">Comparando objetos en Python<\/a><\/li>\n<li class=\"SPOSTARBUST-Related-Post\"><a title=\"Python &#8211; Sumando objetos\" href=\"http:\/\/elclubdelautodidacta.es\/wp\/2015\/05\/python-sumando-objetos\/\" rel=\"bookmark\">Python &#8211; Sumando objetos<\/a><\/li>\n<li class=\"SPOSTARBUST-Related-Post\"><a title=\"Python &#8211; Una tortuga de brocha fina\" href=\"http:\/\/elclubdelautodidacta.es\/wp\/2014\/12\/python-una-tortuga-de-brocha-fina\/\" rel=\"bookmark\">Python &#8211; Una tortuga de brocha fina<\/a><\/li>\n<\/ul><\/div>","protected":false},"excerpt":{"rendered":"<p>Objetivo: comprender los conceptos cr\u00edticos de mutabilidad, inmutabilidad y referencia en Python. Est\u00e1s ante un art\u00edculo esencial en tu formaci\u00f3n como programador en Python. Te llevar\u00e1 s\u00f3lo cinco minutos leerlo, pero puede dar luz sobre conceptos que no resultan ni mucho menos obvios cuando se comienza con Python, particularmente si procedes de otros lenguajes de &hellip; <a href=\"http:\/\/elclubdelautodidacta.es\/wp\/2012\/09\/python-el-sagrado-misterio-de-la-inmutabilidad\/\" class=\"more-link\">Continuar leyendo<span class=\"screen-reader-text\"> \u00abPython: El sagrado misterio de la inmutabilidad\u00bb<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[8],"tags":[375,394,503,265],"class_list":["post-5387","post","type-post","status-publish","format-standard","hentry","category-python","tag-inmutable","tag-mutable","tag-python","tag-referencia"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1PGgv-1oT","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/elclubdelautodidacta.es\/wp\/wp-json\/wp\/v2\/posts\/5387","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/elclubdelautodidacta.es\/wp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/elclubdelautodidacta.es\/wp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/elclubdelautodidacta.es\/wp\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/elclubdelautodidacta.es\/wp\/wp-json\/wp\/v2\/comments?post=5387"}],"version-history":[{"count":18,"href":"http:\/\/elclubdelautodidacta.es\/wp\/wp-json\/wp\/v2\/posts\/5387\/revisions"}],"predecessor-version":[{"id":5405,"href":"http:\/\/elclubdelautodidacta.es\/wp\/wp-json\/wp\/v2\/posts\/5387\/revisions\/5405"}],"wp:attachment":[{"href":"http:\/\/elclubdelautodidacta.es\/wp\/wp-json\/wp\/v2\/media?parent=5387"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/elclubdelautodidacta.es\/wp\/wp-json\/wp\/v2\/categories?post=5387"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/elclubdelautodidacta.es\/wp\/wp-json\/wp\/v2\/tags?post=5387"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}