ROQUES DE ANAGA,. ROQUE DE DENTRO DESDE LA PLAYA DE ALMÁCIGA |
Llegados a este punto ya estamos en disposición de dar un paso más hacia adelante y comenzar a trabajar con el elemento más importante de cualquier lenguaje de programación: la VARIABLE.
Vamos a empezar con una definición: una VARIABLE es una asignación de un espacio determinado en la memoria que sirve para almacenar un determinado dato o valor. ¿A que no nos esperábamos una definición tan enrevesada para algo que se nos antoja tan simple e intuitivo? Bueno... Probemos con esta otra propuesta por el programador experto en JQUERY David Sawyer McFarland: podemos pensar en una variable como un tipo de "cesta". Uno puede poner algo en la cesta, mirar dentro, vaciarla de contenido o, incluso, reemplazar lo que hay dentro por otra cosa (¿nos recuerda esto último al TIPADO DINÁMICO que tocábamos en el capítulo anterior?). Sin embargo, aunque se pueda cambiar lo que hay dentro, sigue siendo la misma cesta.
Mejor, ¿verdad?
En los ejemplos que hemos visto hasta ahora, en concreto, en los que mostramos el uso de los operadores aritméticos, comprobaríamos que una vez ejecutado el cálculo, tanto los datos como el resultado devuelto desaparecen, se evaporan, se esfuman... porque no los hemos guardado en la memoria. O porque no lo hemos metido en la "cesta".
Si consiguiéramos de algún modo guardar nuestros datos y/o resultados, podríamos utilizarlos de nuevo en cualquier otra ocasión, reutilizarlos, llamarlos desde otro programa que estuviéramos codificando sin necesidad de reescribirlo todo de nuevo.
Es aquí donde la VARIABLE acude en nuestro auxilio dado que ésa es precisamente su función: almacena nuestros datos y/o los resultados de la ejecución de nuestros programas en la memoria, y nos permite volver a utilizarlos cuando queramos simplemente llamando o invocando a la variable.
Vale, muy bien. ¿Pero cómo se hace esto?
A través de lo que se denomina DECLARACIÓN DE ASIGNACIÓN.
Para ello lo primero que tenemos que hacer es ponerle un nombre a la variable, es decir, le proporcionamos un IDENTIFICADOR. Lo más aconsejable en este caso es recurrir a un nombre lo más simple posible para almacenar datos sencillos, como 'x', 'a', 'y', 'z', 'x1', etc., o bien proporcionarle un identificador que describa de manera escueta, más o menos descriptiva, aquéllo que pretendemos guardar: 'iva', 'gastos', 'nombre', 'dirección', 'subíndice', etc.
Normalmente emplearemos caracteres alfanuméricos, es decir, letras y cifras sin espacios en blanco entre ellas ('a1', sí; 'a 1', no). Existen una serie de restricciones a la hora de crear un identificador:
- No se puede empezar con un número ('a1' es correcto; '1a' no es correcto).
- No se puede utilizar ningún signo como *, $, /, +, &, etc. El único que se permite es el guión bajo, '_', que puede ir tanto al principio, ( '_x'), como al final ('x_'), como entre medias, utilizándose en este caso para ligar palabras compuestas ('balance_final', 'área_triángulo', 'proveedor_servicios_internet', etc.).
- No se pueden utilizar las llamadas KEYWORDS, es decir, las PALABRAS CLAVE, PALABRAS RESERVADAS o PALABRAS PREDEFINIDAS, que con todos estos nombres nos las podemos encontrar traducidas por ahí. Las KEYWORDS, son palabras que ya disponen en Python de un significado predefinido y que son imprescindibles para llevar a cabo determinadas construcciones de lenguaje. Como podemos imaginar, coinciden con nombres de funciones, como type, por ejemplo; métodos, sentencias, etc. ¿Y por qué es necesario esto? Para que cuando el intérprete de Python esté leyendo un programa o script no entre en conflicto entre un nombre de variable y un nombre que ya conoce, que guarda en su memoria interna y que lleva asignada una determinada acción en la sintaxis del programa.
- No se pueden usar números.
Mostramos a continuación una lista con las palabras reservadas de Python que nunca podremos emplear como nombres de identificadores de variables:
Los identificadores de variables son CASE SENSITIVE, es decir, que el intérprete de Python distingue entre MAYÚSCULAS y minúsculas. 'A' es una variable; y 'a' es otra variable distinta a la anterior.
Ya sabemos cómo identificar, cómo ponerle nombre, en suma, a una variable. Veamos ahora cómo asignarle un valor, esto es, aquéllo que va a almacenar, el "huevo en la cesta". para hacerlo contamos con un operador específico que recibe el nombre de OPERADOR DE ASIGNACIÓN y que se corresponde con el signo =. A través de él ligamos a una variable con el valor que queremos darle. ¿Y qué valor puede ser asignado a una variable? Cualquiera de los que permite Python: INT, FLOAT, STRING, LIST, TUPLE, DICT, SET, etc. Los iremos estudiando poco a poco.
Vamos a verlo con un ejemplo práctico.
Utilizaremos un identificador para ponerle un nombre a un espacio en la memoria (variable) y escogemos...ummm.... 'x', vaya, puesto que cumple todos los requisitos que ya conocemos y que debe tener un identificador de acuerdo a las especificaciones de Python. Le ponemos el signo = para poder vincular un dato o valor a nuestra variable 'x', y a continuación le asignamos ese valor...ummm...'4', por ejemplo.
Así tendremos en el SHELL el siguiente constructo: >>> x = 4. Acabamos de escribir nuestra primera DECLARACIÓN DE ASIGNACIÓN. Ya tenemos nuestro dato, '4', guardado bien calentito en memoria. Nuestro "huevo en la cesta".
Si con esta simple línea de código en el SHELL pulsamos la tecla ENTER, Python nos devuelve 4. Si pulsamos ENTER otra vez, el prompt se nos mostrará vacío señalando una línea de código en blanco. La única forma de obtener de nuevo el INT '4' es reescribiéndolo: >>> 4, una y otra vez. Pero con la DECLARACIÓN DE ASIGNACIÓN, si escribimos 'x' en el siguiente prompt que apunte a una línea vacía, Python nos devolverá su valor asignado, 4, porque ya tenemos el valor almacenado en memoria.
ALMENDRO EN FLOR CON TABAIBAS DULCES AL FONDO EN SANTIAGO DEL TEIDE |
Esto nos permite realizar diferentes operaciones con los datos que hayamos almacenado mediante sendas DECLARACIONES DE ASIGNACIÓN.
Si deseamos guardar el resultado de nuestras operaciones, lógicamente. tendremos que recurrir a identificar una variable nueva y asignarla aplicando la sintaxis que ya conocemos al resultado. Casi siempre la asignaremos a la EXPRESIÓN o ALGORITMO por el que los diferentes datos o valores se relacionan entre sí, en este caso, mediante el uso de los OPERADORES ARITMÉTICOS, lo que nos permite a apuntar a resultados concretos:
Observemos con detalle qué hemos hecho.
Primero hemos declarado una variable 'x' a la que le hemos asignado el valor '4' mediante una DECLARACIÓN DE ASIGNACIÓN, 'y' a continuación hacemos lo propio con la variable 'y' asignándole el valor '3'. Sin embargo, en nuestra tercera línea de código hemos identificado una tercera variable proporcionándole un nombre, un identificador, que en nuestro ejemplo, es 'z' y, mediante el OPERADOR DE ASIGNACIÓN, =, igual que con 'x' y con 'y' le hemos asignado un valor, en esta ocasión le asignamos una EXPRESIÓN matemática: 'x + y'. En la cuarta línea de código tecleamos 'z' en el prompt y, al ejecutar el ENTER, nos devuelve el resultado de la suma de los valores que almacenan 'x' e 'y', es decir, 7. Ahora, 'z' es una variable que almacena el dato de tipo INT '7'. Lo podemos comprobar volviendo a teclear 'z' en el prompt y volviendo a ejecutar ENTER.
>>> z
7
¡Ah! Ahí está. Definitivamente, z = 7.
Pero... un momento. ¿No habíamos establecido justo antes una DECLARACIÓN DE ASIGNACIÓN ligando a 'z' con una EXPRESIÓN, esto es, 'z = x + y' ? ¿Y ahora 'z' guarda el número '7'?
Cierto. Pero es que Python es un lenguaje mágico capaz de prever el futuro.
Es broma. O casi. Lo que sucede es que el intérprete de Python no está leyendo literalmente 'z = x + y'; lo que en realidad está haciendo es vinculando a 'z' el resultado de la expresión, que es un INT, '7'. Porque ya sabe que que x + y = 7 y como 'z = x + y', entonces 'z = 7'. Simple lógica formal: si 'a' implica 'b' y, a su vez, 'b' implica 'c', entonces 'a' implica 'c'. Recordemos que una misma variable puede cambiar de valor todas las veces que sea necesario en el transcurso de una ejecución. Sí, se trata de eso, del TIPADO DINÁMICO que descubrimos en el artículo anterior.
Vamos viendo cómo las cosas, los conceptos, todas estas nociones nuevas van poco a poco encajando, ¿verdad?
Para deja constancia de que esto es así podemos recurrir a nuestra función amiga type() que ya conocemos bien:
Como podemos ver, antes de pedirle a Python el resultado de la expresión 'x + y, ya sabe que ´z´es un número entero (INT), como nos muestra con la primera llamada a la función y lo reafirmamos con la última.
Tomémonos un descanso, un pequeño paréntesis, para formularnos una pregunta. ¿Por qué a las VARIABLES se las llama así? Respuesta de perogrullo; porque puede variar con sólo cambiar sus valores, conmutándolos unos por otros: como ya sabemos, una variable 'x' que en principio tiene un valor asignado de, por ejemplo, '4', dentro del mismo script o programa, se le puede cambiar el valor por otro distinto, por ejemplo, '93' o, incluso, por datos o valores de tipo distinto al tipo del objeto original, es decir, un FLOAT, una STRING, una LIST, una TUPLE, etc. Sí, sí: el TIPADO DINÁMICO. Vamos a verlo:
Tomémonos un descanso, un pequeño paréntesis, para formularnos una pregunta. ¿Por qué a las VARIABLES se las llama así? Respuesta de perogrullo; porque puede variar con sólo cambiar sus valores, conmutándolos unos por otros: como ya sabemos, una variable 'x' que en principio tiene un valor asignado de, por ejemplo, '4', dentro del mismo script o programa, se le puede cambiar el valor por otro distinto, por ejemplo, '93' o, incluso, por datos o valores de tipo distinto al tipo del objeto original, es decir, un FLOAT, una STRING, una LIST, una TUPLE, etc. Sí, sí: el TIPADO DINÁMICO. Vamos a verlo:
En origen le habíamos asignado a la variable 'y' el valor '0.5', un dato o valor de tipo FLOAT que, al sumarlo con el valor almacenado en 'x', el dato de tipo INT '2', Python nos devuelve el FLOAT '2.5'. Nada más obtener el resultado cambiamos el valor de 'y' que pasa a ser '3', un INT. Ahora, tras pulsar ENTER, Python nos devuelve, esta vez, un INT, '5'. Un ejemplo más de TIPADO DINÁMICO.
Yes que la memoria de Python funciona así.
En 1 Python lee el bloque de código y lo primero que encuentra es lo que utiliza. Así ha ocurrido hasta el tercer prompt.
En 2 le proporcionamos una nueva asignación a la variable 'y'. De acuerdo al orden o jerarquía de almacenamiento, se sitúa por delante del anterior valor de 'y'. Cuando Python vuelve a leer la variable 'y', la primera variable con esta referencia que se encuentra es la variable 'y' con el valor modificado a '3'. Y éste será el valor que utilizará Python hasta que se vuelva a conmutar el valor de 'y' por otro valor cualquiera, mientras que su valor original, '0.5', pasa a engrosar al RECOLECTOR DE BASURA. Con respecto a 'x' no hay variación alguna.
Por este motivo a las VARIABLES se las llama... VARIABLES. Y es que el valor de una variable con el mismo identificador es susceptible de variar durante el proceso de ejecución de un programa ninguna vez, una vez o varias, incluso, muchísimas veces si el desarrollo del programa así lo requiere.
Por cierto, aunque parezca un absurdo mencionarlo, tengamos en cuenta que las VARIABLES siempre se declaran primero, a la izquierda del OPERADOR DE ASIGNACIÓN, =. y los datos o valores después, a la derecha del operador. Nunca al revés. Aunque no lo parezca ahora, la cosa tiene su "miga".
Esto es así de acuerdo al FLUJO DE EJECUCIÓN, que veremos en el capítulo que sigue, basado a su vez en el modo de lectura occidental, de manera que cualquier dato que coloquemos a la derecha del operador = de asignación se considerará automáticamente como un valor a almacenar.
Recordemos, a su vez, que Python es un lenguaje de ALTO NIVEL, esto es, próximo al modo natural de expresarse entre los seres humanos. Por este motivo, a pesar de que todos los lenguajes de programación necesitan conocer qué tipo de dato se va a almacenar en una variable, en el caso que compete a Python, éste ya dispone de los mecanismos internos necesarios para conocer el tipo de dato que se va a almacenar sin que nos veamos en la obligación de declararlo expresamente: para una variable con el nombre x, un dato pasado entre comillas a continuación del signo =, como "hola", por ejemplo, será interpretado como una string. Un dígito como 1 o 7516 será interpretado como un tipo de dato int. Si a este tipo de dato le damos un punto que separe unos dígitos de otros, como 75.16, Python lo interpretará como float. Cualquier cosa que pongamos entre corchetes, [ ], desde un único elemento a una colección de n número de elementos, será interpretado como un tipo de dato list. Y así sucesivamente.
Esto significa que en Python, el tipo de dato que almacena una variable viene implícito en el contenido (dato/valor) y no en el contenedor (variable), como sí sucede, por ejemplo, en Java, donde para asignar el valor 17 a una variable a debemos proceder de la siguiente manera: int a=17; donde a, la variable, es el contenedor y 17, el dato/valor es el contenido y, como vemos, hemos tenido que decirle al intérprete de Java que el tipo de dato, 17, el contenido, que va a almacenar la variable a, el contenedor, es un número entero, int, justo antes de declarar la variable.
Afortunadamente, en Python es mucho más sencillo: a= 17.
Pero lo que no podemos hacer es asignar un valor alfanumérico, un signo o un operador porque Python, de acuerdo al FLUJO DE EJECUCIÓN/LECTURA espera, o bien un dato o bien el nombre de una variable que, a su vez, almacene un dato o una colección de datos, lo que en Lógica Formal se conoce como principio de transitividad, en síntesis, si a = b y b = c, entonces a = c.
Si esto no es así, dará error por el lado derecho pero no por el izquierdo debido a que Python asume que lo que se encuentre a la izquierda, siempre y cuando el nombre del objeto se ajuste a los requisitos de declaración establecidos por el propio lenguaje, es el nombre de una variable: x = z daría error porque Python sí sabe lo que es x pero no sabe qué es z, qué tipo de dato es para poder almacenarlo como valor en el espacio de memoria reservado con el referente x en el disco duro de nuestro ordenador., a menos que z fuera el nombre de una variable declarada previamente con su correspondiente valor o colección de valores ya asignada: si z = 735 y a continuación declaramos que x = z, Python asumirá que x guardará, no a z, ¡cuidado!, sino al valor, 735, que hasta ahora había almacenado z y que se transfiere a x en virtud del operador = de asignación. Así x = 735 mientras que el espacio de memoria que habíamos nombrado como z queda vacío y dispuesto a acoger a algún otro valor que le queramos pasar.
Lo vemos en el siguiente esquema:
Tengamos en cuenta que este proceso de transferencia no es un tipado dinámico, ya que lo que cambia es el espacio de memoria donde se almacena el objeto, pero no el tipo de dato que sigue siendo el objeto 3 que, en todo momento, continua siendo un tipo de dato int.
Antes de concluir es necesario, entre ladrido y ladrido, hacer la siguiente aclaración: al contrario de lo que sucede con otros lenguajes de programación, como Javascript por ejemplo, que emplean una sentencia específica para declarar la variable ('var', para el ejemplo), en Python no se declaran las variables. Éstas se crean en el mismo instante en que, por mediación del OPERADOR DE ASIGNACIÓN, =, recibe un dato o valor. Entonces, y sólo entonces, la variable comienza a "existir".
No. Nos nos estamos refiriendo a una selección de actores y actrices para participar en una película o en una serie televisiva. Pero sí a una de sus acepciones, más o menos asimilable en ambos casos, para actores y actrices y para las variables bajo la noción de 'to cast ··> (skin)', "mudar (de piel)". Y de esto se trata: en el caso de las variables,de mudar su piel,...su tipo.
Por este motivo a las VARIABLES se las llama... VARIABLES. Y es que el valor de una variable con el mismo identificador es susceptible de variar durante el proceso de ejecución de un programa ninguna vez, una vez o varias, incluso, muchísimas veces si el desarrollo del programa así lo requiere.
Por cierto, aunque parezca un absurdo mencionarlo, tengamos en cuenta que las VARIABLES siempre se declaran primero, a la izquierda del OPERADOR DE ASIGNACIÓN, =. y los datos o valores después, a la derecha del operador. Nunca al revés. Aunque no lo parezca ahora, la cosa tiene su "miga".
Esto es así de acuerdo al FLUJO DE EJECUCIÓN, que veremos en el capítulo que sigue, basado a su vez en el modo de lectura occidental, de manera que cualquier dato que coloquemos a la derecha del operador = de asignación se considerará automáticamente como un valor a almacenar.
Recordemos, a su vez, que Python es un lenguaje de ALTO NIVEL, esto es, próximo al modo natural de expresarse entre los seres humanos. Por este motivo, a pesar de que todos los lenguajes de programación necesitan conocer qué tipo de dato se va a almacenar en una variable, en el caso que compete a Python, éste ya dispone de los mecanismos internos necesarios para conocer el tipo de dato que se va a almacenar sin que nos veamos en la obligación de declararlo expresamente: para una variable con el nombre x, un dato pasado entre comillas a continuación del signo =, como "hola", por ejemplo, será interpretado como una string. Un dígito como 1 o 7516 será interpretado como un tipo de dato int. Si a este tipo de dato le damos un punto que separe unos dígitos de otros, como 75.16, Python lo interpretará como float. Cualquier cosa que pongamos entre corchetes, [ ], desde un único elemento a una colección de n número de elementos, será interpretado como un tipo de dato list. Y así sucesivamente.
Esto significa que en Python, el tipo de dato que almacena una variable viene implícito en el contenido (dato/valor) y no en el contenedor (variable), como sí sucede, por ejemplo, en Java, donde para asignar el valor 17 a una variable a debemos proceder de la siguiente manera: int a=17; donde a, la variable, es el contenedor y 17, el dato/valor es el contenido y, como vemos, hemos tenido que decirle al intérprete de Java que el tipo de dato, 17, el contenido, que va a almacenar la variable a, el contenedor, es un número entero, int, justo antes de declarar la variable.
Afortunadamente, en Python es mucho más sencillo: a= 17.
Pero lo que no podemos hacer es asignar un valor alfanumérico, un signo o un operador porque Python, de acuerdo al FLUJO DE EJECUCIÓN/LECTURA espera, o bien un dato o bien el nombre de una variable que, a su vez, almacene un dato o una colección de datos, lo que en Lógica Formal se conoce como principio de transitividad, en síntesis, si a = b y b = c, entonces a = c.
Si esto no es así, dará error por el lado derecho pero no por el izquierdo debido a que Python asume que lo que se encuentre a la izquierda, siempre y cuando el nombre del objeto se ajuste a los requisitos de declaración establecidos por el propio lenguaje, es el nombre de una variable: x = z daría error porque Python sí sabe lo que es x pero no sabe qué es z, qué tipo de dato es para poder almacenarlo como valor en el espacio de memoria reservado con el referente x en el disco duro de nuestro ordenador., a menos que z fuera el nombre de una variable declarada previamente con su correspondiente valor o colección de valores ya asignada: si z = 735 y a continuación declaramos que x = z, Python asumirá que x guardará, no a z, ¡cuidado!, sino al valor, 735, que hasta ahora había almacenado z y que se transfiere a x en virtud del operador = de asignación. Así x = 735 mientras que el espacio de memoria que habíamos nombrado como z queda vacío y dispuesto a acoger a algún otro valor que le queramos pasar.
Lo vemos en el siguiente esquema:
Tengamos en cuenta que este proceso de transferencia no es un tipado dinámico, ya que lo que cambia es el espacio de memoria donde se almacena el objeto, pero no el tipo de dato que sigue siendo el objeto 3 que, en todo momento, continua siendo un tipo de dato int.
Antes de concluir es necesario, entre ladrido y ladrido, hacer la siguiente aclaración: al contrario de lo que sucede con otros lenguajes de programación, como Javascript por ejemplo, que emplean una sentencia específica para declarar la variable ('var', para el ejemplo), en Python no se declaran las variables. Éstas se crean en el mismo instante en que, por mediación del OPERADOR DE ASIGNACIÓN, =, recibe un dato o valor. Entonces, y sólo entonces, la variable comienza a "existir".
CASTING:
No. Nos nos estamos refiriendo a una selección de actores y actrices para participar en una película o en una serie televisiva. Pero sí a una de sus acepciones, más o menos asimilable en ambos casos, para actores y actrices y para las variables bajo la noción de 'to cast ··> (skin)', "mudar (de piel)". Y de esto se trata: en el caso de las variables,de mudar su piel,...su tipo.
Básicamente, se considera casting en programación a la facultad de convertir, trasmutar, un tipo de dato en otro tipo de dato distinto. Por ejemplo convierte un tipo de dato cadena, string, en un valor de tipo entero, int. Como una especie de conversión entre tipos de datos diferentes.
Tengamos en cuenta que no es posible realizar operaciones entre tipos de datos distintos.
Esto se puede hacer de manera implícita o explícita.
HAY, VAMOS A DECIRLO ASÍ, UNA CONVENCIÓN DE ESTILOS PARA LAS VARIABLES QUE ALMACENAN CONSTANTES DE CUALQUIER TIPO, YA QUE PYTHON NO LES PROPORCIONA UN SOPORTE ESPECIAL: SE BASA, SIMPLEMENTE, EN ESCRIBIRLAS EN MAYÚSCULAS.VEAMOS:
v_luz = 3*(10**18) ❌, V_LUZ = 3*(10**18) ✔; constante_gravitacion = 9.8 ❌, CONSTANTE_GRAVITACION = 9.8 ✔.
Finalmente, para concluir y por aquéllo de que el saber no ocupa lugar, explicaremos aquí como funciona el proceso de almacenado de datos en memoria, un tanto particular en el caso de Python, y cómo se eliminan las variables que han recibido un nuevo dato o valor habiendo conservado la variable el mismo nombre.
Partimos de una variable que lleva el nombre A y que usamos como referencia para asignar un espacio de memoria. Contamos para ello con un pequeñito set de memoria con tan sólo 48 celdas para almacenar nuestros datos. A esta variable A le asignamos mediante el operador = de asignación el valor 3, un tipo de dato int (integer). Justo en este momento mágico, el intérprete de Python le asigna una de las 48 celdas disponibles en nuestro set de memoria, en este caso, la celda 32, donde se guarda y almacena entre mullidos algodones binarios. Pero he aquí que nosotros, espíritus inquietos, decidimos asignarle a nuestra variable A un nuevo valor, en esta ocasión, otro tipo de dato int, el 46. ¿Y qué sucede entonces? Pues que, como ya hemos visto en el esquema de arriba, el intérprete de Python asignará un nuevo espacio de memoria, una nueva celda, para almacenar nuestro dato 46, con la misma referencia A, pero en una posición anterior a la celda original, es decir, cualquiera de las otras 31 celdas vacías anteriores, donde, ¡cuidado! nuestra primera variable A con su valor 3, continúa existiendo. Esto significa que en nuestro set de memoria coexisten dos celdas ocupadas con sendos valores, distintos entre sí, 3 y 46, referenciadas con el mismo nombre, A.
Sin embargo, y como también sabemos, el flujo de lectura de memoria de Python se detendrá en la primera ocurrencia de A, y como ésta vale ahora 46, será este el valor que podemos recuperar, mientras que la segunda ocurrencia de A, en la celda 32 y con un valor almacenado de 3, se convierte en inaccesible para el programa y, en segunda instancia, para nosotros mismos como programadores.
¿Y cómo se libera, pues, ése espacio de memoria inútil? Pues es aquí donde entra el recolector de basuras.
Digamos que Python dispone de una especie de gerente de almacén (de memoria), de encargado, al que el intérprete llama cada vez que declaramos una nueva variable y, en consecuencia, asigna una nueva celda donde almacenar el nuevo valor. En este caso, surge un garbage, una especie de "camión de la basura" que recorre pausadamente nuestro set de memoria "limpiando" las celdas de sus valores "inalcanzables" por el programa y "liberando", por consiguiente, espacio de memoria. ¿Y cómo lo hace? Pues porque el intérprete de Python le sopla el nombre de una variable, en nuestro ejemplo, A, y el bueno del garbage recorre nuestro set de memoria localizando todas las celdas que tengan ese mismo referente A, en nuestro ejemplo, las celdas 32 y 28. Lo que hará será identificar qué celda con el nombre A es la primera en encontrarse el intérprete de Python en el curso de lectura de memoria, esto es, la celda 28, y vaciar de contenido cualquier otra celda que se encuentre a continuación de ésta, en nuestro ejemplo, la celda 32, que tenga ése mismo nombre A, y que se corresponden a aquéllas a las que el programa, como acabamos de decir, ya no puede acceder.
Veámoslo gráficamente:
Tengamos en cuenta que no es posible realizar operaciones entre tipos de datos distintos.
Esto se puede hacer de manera implícita o explícita.
CASTING IMPLÍCITO:
El que realiza directamente el propio intérprete de Python cuando asignamos un nuevo tipo de dato a un mismo espacio de memoria, reservado e identificado bajo un mismo nombre de variable.
CASTING EXPLÍCITO:
El que realizamos nosotros mismos a partir de una función conversora ('to convert' en Python es similar al concepto de 'to cast', converting = casting) proporcionada por el lenguaje, cediéndonos todo el control de la conversión, manteniendo el mismo nombre de la variable.
Veamos un ejemplo de lo que decimos aquí:
HAY, VAMOS A DECIRLO ASÍ, UNA CONVENCIÓN DE ESTILOS PARA LAS VARIABLES QUE ALMACENAN CONSTANTES DE CUALQUIER TIPO, YA QUE PYTHON NO LES PROPORCIONA UN SOPORTE ESPECIAL: SE BASA, SIMPLEMENTE, EN ESCRIBIRLAS EN MAYÚSCULAS.VEAMOS:
v_luz = 3*(10**18) ❌, V_LUZ = 3*(10**18) ✔; constante_gravitacion = 9.8 ❌, CONSTANTE_GRAVITACION = 9.8 ✔.
Partimos de una variable que lleva el nombre A y que usamos como referencia para asignar un espacio de memoria. Contamos para ello con un pequeñito set de memoria con tan sólo 48 celdas para almacenar nuestros datos. A esta variable A le asignamos mediante el operador = de asignación el valor 3, un tipo de dato int (integer). Justo en este momento mágico, el intérprete de Python le asigna una de las 48 celdas disponibles en nuestro set de memoria, en este caso, la celda 32, donde se guarda y almacena entre mullidos algodones binarios. Pero he aquí que nosotros, espíritus inquietos, decidimos asignarle a nuestra variable A un nuevo valor, en esta ocasión, otro tipo de dato int, el 46. ¿Y qué sucede entonces? Pues que, como ya hemos visto en el esquema de arriba, el intérprete de Python asignará un nuevo espacio de memoria, una nueva celda, para almacenar nuestro dato 46, con la misma referencia A, pero en una posición anterior a la celda original, es decir, cualquiera de las otras 31 celdas vacías anteriores, donde, ¡cuidado! nuestra primera variable A con su valor 3, continúa existiendo. Esto significa que en nuestro set de memoria coexisten dos celdas ocupadas con sendos valores, distintos entre sí, 3 y 46, referenciadas con el mismo nombre, A.
Sin embargo, y como también sabemos, el flujo de lectura de memoria de Python se detendrá en la primera ocurrencia de A, y como ésta vale ahora 46, será este el valor que podemos recuperar, mientras que la segunda ocurrencia de A, en la celda 32 y con un valor almacenado de 3, se convierte en inaccesible para el programa y, en segunda instancia, para nosotros mismos como programadores.
¿Y cómo se libera, pues, ése espacio de memoria inútil? Pues es aquí donde entra el recolector de basuras.
Digamos que Python dispone de una especie de gerente de almacén (de memoria), de encargado, al que el intérprete llama cada vez que declaramos una nueva variable y, en consecuencia, asigna una nueva celda donde almacenar el nuevo valor. En este caso, surge un garbage, una especie de "camión de la basura" que recorre pausadamente nuestro set de memoria "limpiando" las celdas de sus valores "inalcanzables" por el programa y "liberando", por consiguiente, espacio de memoria. ¿Y cómo lo hace? Pues porque el intérprete de Python le sopla el nombre de una variable, en nuestro ejemplo, A, y el bueno del garbage recorre nuestro set de memoria localizando todas las celdas que tengan ese mismo referente A, en nuestro ejemplo, las celdas 32 y 28. Lo que hará será identificar qué celda con el nombre A es la primera en encontrarse el intérprete de Python en el curso de lectura de memoria, esto es, la celda 28, y vaciar de contenido cualquier otra celda que se encuentre a continuación de ésta, en nuestro ejemplo, la celda 32, que tenga ése mismo nombre A, y que se corresponden a aquéllas a las que el programa, como acabamos de decir, ya no puede acceder.
Veámoslo gráficamente:
SHORTHAND:
Las shorthand ('taquigrafía', en español) constituye un procedimiento muy útil por el que Python nos permite reducir código para efectuar diversos tipos de operaciones, como por ejemplo, asignación o reasignación de valores, en el caso que nos ocupa, de lo más sencillo como vamos a ver, o en sintaxis más sofisticadas, como las funciones lambda o los decoradores (decorators) que estudiaremos juntos más adelante.
En la nomenclatura de Python se las conoce también como asignaciones abreviadas y aún las veremos nuevamente más adelante explicadas con mayor detalle.
Nos basta ahora con saber que podemos asignar valores a diferentes variables en una misma línea de código mediante un procedimiento first to first, de modo que a la primera variable entre una serie de variables separadas por comas, le corresponde, a continuación del operador = de asignación, el primer valor, de entre una serie de valores separados por comas; a la segunda variable, le corresponde el segundo valor; a la tercera el tercero; y así sucesivamente hasta completar los pares variable/valor.
Los valores pueden ser del mismo tipo o de tipos diferentes. Por eso no se van a pelear. Ahora lo que sí resulta un requisito imprescindible es que el número de variables coincida con el número de valores a asignar, ya que de no ser así, el intérprete de Python nos mostraría un error (lanzaría una excepción, que así se llama técnicamente el tortazo) de tipo ValueError (error en la la manipulación de valores). Veámoslo:
Pero Python va más allá, y no sólo nos permite asignar variables a múltiples valores en una misma línea de código sino que, además, nos permite re-asignar (asignaciones cruzadas) valores a distintas variables también en una misma línea de código, es decir, si a una variable a le hemos asignado un valor x y a una variable b le hemos asignado un valor z, conseguir de una manera sencilla, abreviada, en una misma línea de código, que ahora la variable a tenga el valor z y que la variable b tenga el valor x.
Vamos a despejar el galimatías con un ejemplo:
A que mola, ¿eh?
Existe aún una forma harto curiosa de "recuperar" valores de variables en una codificación a través del uso del guión bajo: _. Podemos entenderlo como una suerte de comodín al que el intérprete de Python asigna por defecto el último valor de una expresión dada. Vamos a verlo con un ejemplo:
Teniendo en cuenta que el guión bajo es una suerte de variable-comodín que almacena el valor resultante de la ejecución de una expresión, podemos aplicarle funciones nativas de Python sin ningún tipo de cortapisa. Veamos un ejemplo con len(), una función que determina la longitud de una secuencia o colección de datos (veremos lo que es una secuencia un poco más adelante):
GUIÓN BAJO:
Existe aún una forma harto curiosa de "recuperar" valores de variables en una codificación a través del uso del guión bajo: _. Podemos entenderlo como una suerte de comodín al que el intérprete de Python asigna por defecto el último valor de una expresión dada. Vamos a verlo con un ejemplo:
Teniendo en cuenta que el guión bajo es una suerte de variable-comodín que almacena el valor resultante de la ejecución de una expresión, podemos aplicarle funciones nativas de Python sin ningún tipo de cortapisa. Veamos un ejemplo con len(), una función que determina la longitud de una secuencia o colección de datos (veremos lo que es una secuencia un poco más adelante):
Tengamos en cuenta que el guión bajo puede ser una referencia al nombre de una variable por sí mismo, es decir, que no entra dentro de las restricciones de nombres de variables de Python. Como nos podemos imaginar, esto no es precisamente lo más recomendable aunque, funcionar, lo que se dice funcionar, funciona:
PAISAJE DE PRIMAVERA EN EL VALLE DE SANTIAGO DEL TEIDE, OESTE DE TENERIFE. |
Hola. Magnífico trabajo, eres genial!
ResponderEliminarTengo una duda, ¿Es posible que en Python 3.7.3 y sublime text, no se reconozca la "función comodín" del guión bajo? Es que a mí me dice NameError: name '_' is not defined. Muchas gracias Gauber.
Hola, Roxie. Muchísimas gracias por tus palabras. Todo un aliento para continuar. Con respecto a tu duda, he comprobado que en la versión más avanzada de Python de la que dispongo, la 3.8, un poco superior a la tuya, sí que funciona el comodín, luego no se trata de un aspecto de la sintaxis de Python que se haya eliminado en versiones más modernas del lenguaje. También he comprobado que en en el IDE que utilizo, Visual Studio Code (particularmente, no utilizo Sublime Text), también me sale el mismo "error" que me comentas. ¿La razón? Sinceramente, no lo sé, pero parece que es un recurso sintáctico que sí está disponible en el IDLE de Python pero no así en algunos IDEs, como Sublime Text o Visual Studio Code. Ten en cuenta, de todas formas, que el recurso al comodín debe ser algo muy, pero que muy puntual, y sólo en scripts de unas pocas líneas de código porque su valor varía por defecto con cada llamada que implique su participación, por lo que resulta casi imposible de controlar. Si me admites un consejo, utiliza siempre variables con nombre, incluso, en scripts sencillos y con pocas líneas de código. Puedes probar si el comodín "_" funciona en IDEs dedicados, esto es, con IDEs que son específicos para codificar con Python y no con otro lenguaje de programación, como PyCharm, del que te puedes descargar una versión gratuita que funciona bastante bien, y que precisamente, por ser dedicado, igual sí admite el comodín. Saludos y muchas gracias de nuevo por tus palabras.
ResponderEliminarMe parece que te voy a dar las gracias por cada tema. Fenómeno
ResponderEliminarHola, Michelle, de nuevo.¡Ja, ja!No es necesario. Los fenómenos sois vosotros, que mantenéis este blog con vuestras visitas y comentarios. Saludos.
ResponderEliminarIncreíble, una pregunta es posible darle a una variable varios valores para que se le pueda agregar a otra operación. me refiero a que x vale 0, 15 y 8 y quiero que este este se opere en y= x+9.
ResponderEliminarHola y muchas gracias por tu comentario. En respuesta a tu pregunta, no. Toda variable no es otra cosa que una referencia a un espacio de memoria en el sistema donde Python almacena UN DATO, para poder recuperarlo más adelante en el curso de la ejecución de un programa. Cuando asignamos un dato, en su caso, un número, 0, 15 o 8, ése número será el dato que ocupe ése espacio de memoria seleccionado por Python para almacenarlo. Ahora bien, en virtud del Alto Tipado Dinámico del programa, el valor que inicialmente asignemos a una misma referencia, siguiendo con su pregunta, x, y por ejemplo x=0, puede cambiar a lo largo de nuestro programa, bien por que lo hagamos nosotros mismos reasignando un valor nuevo a x, por ejemplo, x=15 o x="question" o x= [1,2,3,4,5], o porque el propio programa, porque así lo hayamos codificado nosotros, reasigne él mismo un valor nuevo a x. Esto de mantener un único dato a una misma y única variable es fundamental para mantener la coherencia a la hora de ejecutarse un programa , y para el propio programador y quienes vayan a sostener el programa con el tiempo para no "liarse" con valores distintos asignados a una misma referencia. Por eso, aparte de imposible, ni es bueno ni recomendable.
EliminarAdemás, si establece esta forma de asignación: x = 0, 15, 8 y pulsas Intro, lo que obtiene es un ÚNICO DATO: (0, 15, 8), esto es, un tipo de dato tupla (3-tupla), y que podrá ver más adelante en el capítulo dedicado a las tuplas.
Lo que sí puede hacer es una asignación múltiple en una sóla línea de código, que sería como sigue: x1, x2, x3 = 0, 15, 8 donde, tras pulsar Intro, tendrá como resultado las siguientes asignaciones: x1 = 0, x2 = 15 y x3 = 8. El haber usado x1, x2 y x3, es decir, un mismo nombre, x, con una pequeña variación para distinguirlas entre sí (1,2,3 para x1, x2 y x3) puede ser una forma para controlar que un mismo nombre de variable que, como ya decimos, debe procurarse siempre especifique lo mejor posible para qué se va a utilizar y ayudar así a la comprensión del código para terceros, pueda indicarnos que se va a utilizar de una forma determinada.
Esperamos que esta respuesta tan larga, por la que pedimos disculpas, no haya resultado cansina y le haya aclarado sus dudas. Saludos.
Voy a cumplir 60 años, soy autodidacta, he incursionado en varios lenguajes y he leído muchos manuales y cursos, le recomiendo a cualquier persona que tenga interés en aprender un lenguaje de programación, no importa su edad, no dude en aprender PYTHON. Poder tener acceso a este !EXCELENTE! trabajo, es una maravilla, es estupendo, claro, conciso y suficientemente profundo para despertar un interés mayor por este lenguaje. Muchas Gracias por dedicar parte de su tiempo y le deseo el mejor de los éxitos en cualquier área que se desarrolle.
EliminarBuenas tardes desde cuando escribo, sr. Tyrone. No puedo estar más de acuerdo con Ud. hasta el primer punto y seguido. Secundo su opinión de principio a fin y, por su esfuerzo personal, debo felicitarle: es Ud un ejemplo admirable de lo que pretendemos con este blog. A partir de ese primer punto y seguido, sus palabras, sus elogios, el sentido de cuanto expone, me enmudecen. Sólo puedo darle las gracias de todo corazón y desearle, igualmente, todo lo mejor. Saludos, sr. Tyrone.
Eliminar