TUPLAS

RETAMA EN FLOR EN PRIMER PLANO Y FLORACIÓN EN LA PRIMAVERA DEL PARQUE NACIONAL DE LAS CAÑADAS DEL TEIDE, TENERIFE.

      En Python, una tupla es una secuencia (v. entrada correspondiente para refrescarnos un poco la memoria), con evidentes similitudes con el objeto de tipo list que acabamos de estudiar: estamos hablando de una estructura ordenada, esto es, que siempre que la invoquemos se nos mostrará tal cual la hemos escrito, no como en los conjuntos, set, que recordemos nos muestra los datos en un orden aleatorio, que almacena referencias, no lo olvidemos, de objetos que pueden ser de distintos tipos separados por comas aunque, en su caso, hablamos de una estructura de datos INMUTABLE, que es su característica fundamental, esto es, que no puede ser modificada. Otra diferencia, en este caso sólo a nivel ortográfico, es que mientras que en las listas las referencias a objetos se delimitan entre corchetes y los conjuntos entre llaves, en el caso de las tuplas los datos se encapsulan entre paréntesis:

                                                      CONJUNTO(SET) ···> { }    LISTA(LIST) ···> [ ]   TUPLA(TUPLE) ···> ( )




Las tuplas, por otra parte, comparte con las strings su condición de secuencia inmutable y como el resto de las secuencias, soporta idéntica sintaxis para extraer elementos o, lo que es lo mismo, para identificar un elemento por su índice, o troceando mediante rebanadas (técnica de slicing), así como la iteración, el recorrido por todos y cada uno de sus elementos constitutivos a través del bucle for/in. podemos verlo en el siguiente ejemplo:



No parece que tenga una gran complicación, ¿verdad? Pues continuamos conociendo un poco mejor a nuestra nueva amiga.
Ya hemos dejado claro que una tupla es una secuencia inmutable, pero eso no significa que sea "estrictamente" intocable...¡Ah! ¿No?... Pues no. ¡Anda! ¿Y cómo lo hacemos? Recurriendo a un método muy, muy simple: transformamos una tupla en una lista mediante la función conversora list(tuple), una vez convertida en lista aprovechamos las operaciones y los método que ya conocemos y, una vez satisfechos con los cambios que hemos causado, volvemos a convertir nuestra lista en una tupla, esta vez, mediante la función conversora tuple(list).
Vamos a ilustrarlo con un ejemplo: supongamos que tenemos una tupla t formada por números y queremos ordenarlos de menor a mayor. Veamos cómo debemos proceder para conseguirlo:


1. Creamos la tupla. Destaquemos que hemos introducido elementos repetidos. Las listas, las cadenas literarias y las tuplas admiten elementos repetidos, pero los conjuntos y diccionarios, no.
2. Aplicamos la función integrada list() e introducimos como argumento el identificador de variable que le hemos proporcionado a nuestra tupla, esto es, t.
3.  A través de la función type() inquirimos la naturaleza de t por aquéllo de que el saber no ocupa lugar, Python nos confirma que t es una tupla.
4. Recurrimos a una asignación: creamos una variable a la que referenciamos como a y le asignamos el resultado de la aplicación a t de la función list().
5. Al pasarle la función type() comprobamos que, ahora, a es una lista que contiene exactamente y en el mismo orden y cantidad los ítems que configuraban nuestra tupla t original.
6. Aprovechando que ahora tenemos una lista para aplicar el método que nos interesa, en este caso, lista.sort().
7. Aquí podemos ver el resultado: una lista con todos sus ítems ordenados de menor a mayor.
8. Ahora ya sólo nos queda nos queda invocar a la función conversora tuple() para obtener de nuevo una tupla. Obviamente le asignaremos una variable, que será de nuevo t como podríamos haber elegido otra cualquiera, para guardar en nuestra memoria el resultado.
9. ¡Voilà! Ya tenemos nuestra inmutable/inmodificable tupla original fácilmente mutada/modificada a nuestro gusto.

COSTA DE TAGANANA, AL FONDO, Y VISTA DE LOS ROQUES DE ANAGA EN EL CENTRO DE LA IMAGEN. NORTE DE ANAGA. NORESTE DE TENERIFE.

Conviene destacar que esta nueva tupla t. no es ya nuestra tupla t original, dado que esta última ha sido "borrada" de la memoria y su espacio en ella puesto a disposición de Python para almacenar cualquier otra cosa: la nueva tupla t es otra tupla distinta a la tupla t original que ocupa su propio espacio de memoria.
Como podemos comprender, dada la naturaleza inmutable de las tuplas, si recurrimos a ellas,  nos convendría guardar en las mismas referencias a objetos que por su propia condición sean siempre los mismos o, al menos, casi siempre: los días de la semana, por ejemplo, ya que son siempre los mismos, siempre son siete y siempre se suceden en el mismo orden; los meses del año; horas del día; planetas del sistema solar; elementos de la tabla periódica; constantes físico-químicas; un listado con n números primos; la lista completa de los reyes godos ( y no es broma); etc. O también, información sensible que no debe ser modificada, como una colección de contraseñas de usuario o de referencias a archivos, por ejemplo.
Ya que hemos presentado en sociedad a la función tuple(), al igual que la función list(), int(), float(), str() o la función set(), una función conversora, continuamos con ella y señalamos que si no le pasamos argumento alguno, nos devuelve una tupla vacía, y que con un argumento, ya que sólo acepta uno, nos devolverá una copia del argumento mostrada como tupla. Por cierto, a una tupla con un solo elemento se la llama tupla unitaria, por razones evidentes. Recuerda que si tenemos un único elemento debemos poner una coma al final del mismo para que Python "sepa" que es una tupla.
Observemos el siguiente ejemplo:



El recurso a la función set() aplicado sobre una tupla permite eliminar los ítems repetidos, cosa que ya sabíamos cuando analizamos al propio objeto y cuando estudiamos las listas en los apartados anteriores. Comprobamos que al devolvernos el resultado de la conversión obtenemos un conjunto con los ítems ya ordenados de menor a mayor, ajeno a la aleatoriedad que caracteriza a los conjuntos.
En el segundo caso, aplicamos una sintaxis en la que una misma línea de código escribimos sucesivamente varias funciones y métodos, separados por punto y coma, ;, para obtener el resultado final: una tupla ordenada de mayor a menor (método list.reverse())  y con un ítem más añadido al cabo de la colección (list.append(ítem)), en nuestro ejemplo, el número 0. No olvidemos que este último método añade un ítem al final de la lista, con lo que si hubiéramos pasado como argumento el número 10, hubiera "roto" nuestra pretensión de crear una lista con los valores ordenados de mayor a menor.

CASCADA DE AGUA PERMANENTE EN LA CABECERA DEL BARRANCO DE CUEVAS NEGRAS,  ENTRE LOS MUNICIPIOS DE LOS SILOS Y BUENAVISTA, MACIZO DE TENO, NOROESTE DE TENERIFE.

      MÉTODOS DE LAS TUPLAS

   
      Por su condición de inmutables, dicho de otra forma, por su versatilidad limitada, sólo cuenta con dos métodos. Poquitos, la verdad, pero eso sí, bien avenidos. Por esta razón no vamos a desarrollar un apartado específico para tratarlos como hemos hecho hasta ahora con los métodos de las strings y de las listas: nos basta con hacer un pequeño aparte en este capítulo para desarrollarlas y estudiarlas.

     

       1) TUPLE.COUNT(ITEM):

   
      Nos devuelve el número de veces que un determinado ítem aparece en una tupla.


      2) TUPLE.INDEX(ITEM):

   
     Nos devuelve el índice de la primera posición en la que encuentra dicho ítem de izquierda a derecha:



Ambos métodos tienen sus homónimos correspondientes en las listas. Además, podemos usar con las tuplas los operadores +, de concatenación, y *, de duplicación/multiplicación.


Y también los operadores de verificación o pertenencia in/not in.



También podemos recurrir a los operadores de asignación aumentada += y *= para operar con las tuplas.


      Te recuerdo con un ladrido de los míos que una "asignación aumentada" equivale a la siguiente fórmula:

                                                A += 8 <==> A = A + 8


También, ya que estamos en faena, podemos aplicar los operadores de comparación (<, <=, ==, !=, >=, >), pudiendo comparar tanto las tuplas entre sí como sus elementos, tal y como se demuestra a continuación. ¡Guau!



Aquí podemos hacer una puntualización con respecto al estilo de codificación. Algunos programadores optan por no usar los paréntesis cuando escriben una tupla ya que, por defecto, Python considera que una sucesión o colección de valores separados por comas es de por sí una tupla.


Sin embargo, otros programadores optan por utilizar los paréntesis cuando resulta estrictamente necesario, como en el ejemplo que proponemos a continuación, en el que es posible confundir una función con tres argumentos con una función con una tupla por argumento.


Otros prefieren usar los paréntesis siempre. Nuestro consejo es que en un principio, escojamos escribir siempre los paréntesis para reducir al máximo los posibles errores de interpretación y que, cuando ganemos soltura, desarrollemos nuestro propio estilo de codificación.
Podemos anidar tuplas dentro de otras tuplas (tuplas anidadas) y extraer los elementos que queramos de ellas recorriendo a las rebanadas y a los indexados, cualquiera que fuera su nivel de profundidad.



A veces, las estructuras de datos anidadas se tornan muy complejas y, como consecuencia, nos pueden inducir un cierto grado de confusión. Podemos sin embargo despejar un poco el panorama si recurrimos a nombrar las distintas posiciones del índice. Lo ilustramos con el ejemplo que sigue:


Podemos construir tuplas, como sabemos bien, secuenciando referencias a objetos. Esto es lo que se conoce como "desempaquetado de tuplas", tal y como ya lo hicimos en su momento con el "desempaquetado de listas" en un apartado anteriores..




   
      POR CIERTO, PODEMOS ELIMINAR UNA TUPLA MEDIANTE LA
INSTRUCCIÓN del:






Podemos calcular también aspectos que afectan a los ítems que integran una tupla, como su longitud o tamaño, su valor máximo o su valor mínimo.



Si quisiéramos construir una tupla con un único ítem alojado en su interior, debemos escribir una coma después del mismo pues, de no hacerlo, Python lo interpretará como una llamada normal y corriente a un dato. Las tuplas vacías no requieren comas.



Recapitulando, Python interpreta (y devuelve) que una sucesión simple de datos asociados a una variable y separados por comas es un objeto de tipo tupla (tuple), entre otras cosas por razones de seguridad, ya  que por su condición de inmutables, contribuye a preservar así la integridad de la asignación frente a "accidentes", intentos no autorizados de modificación de datos, etc. Como podemos ver en el ejemplo siguiente, añadir una coma al final del último elemento de la secuencia proporciona resultados idénticos a no hacerlo, pero de cara a clarificar el código, no es mala opción recurrir a esa posibilidad.



      EN PYTHON, LAS COMAS EJERCEN COMO OPERADORES SECUNDARIOS, POR DECIRLO ASÍ, CON UN SIGNIFICADO PROPIO EN EL CÓDIGO. POR ELLO, CUANDO ASIGNAMOS UNA COLECCIÓN DE DATOS A UNA ÚNICA VARIABLE SEPARADOS POR COMAS, AUTOMÁTICAMENTE, COMO ACABAMOS DE VER, LO CONVIERTE EN TUPLA. PERO SI QUISIÉRAMOS CONVERTIR EN TUPLA UN ÚNICO VALOR, UN ENTERO, POR EJEMPLO, NOS BASTA CON AÑADIR UNA COMA DETRÁS. ESTO RESULTA MUY ÚTIL PARA, POR EJEMPLO, EVITAR LAS INYECCIONES MALICIOSAS EN UNA TABLA DE DATOS ALOJADA EN UN SERVIDOR.




Las tuplas permiten el formateo de textos (strings) y, además, dado que las claves (keys) de los diccionarios deben ser inmutables, como veremos más adelante en su apartado correspondiente, los valores de una tupla pueden utilizarse, total o parcialmente,  como tales claves de diccionario, cosa que no puede hacer, por ejemplo, una lista. Veámoslo:



Para concluir, simplemente volver a insistir en el hecho de que las tuplas resultan muy útiles cuando construimos secuencias de ítems cerrados, inmanentes (permanecen inmodificados en el tiempo). Por este motivo las tuplas son más homogéneas (ítems del mismo tipo) que la listas, más heterogéneas y versátiles. Además, por su inmutabilidad, son ideales para contener datos sensibles como passswords, datos personales o privados, nombres de archivos más o menos confidenciales,... De hecho, trabajan más rápido que las listas de cara a secuencias de datos que no tengamos intención (o posibilidad) de modificar, como días de la semana, husos horarios, meses del año, genealogía, elementos constitutivos de compuestos químicos, etc. Constituyen un recurso de almacenado de valores muy útil cuando trabajamos con datos pasados en el tiempo y que, en consecuencia, no se pueden alterar o modificar en modo alguno: fechas (efemérides), resultados deportivos, publicaciones, cronología, etc.
Podemos comprobarlo en el ejemplo siguiente. Incluiremos elementos que aún no hemos visto en este manual, pero nos permitirá tener una cierta perspectiva de la manera en la que podemos trabajar con las tuplas en nuestros códigos:

EJEMPLO DE TUPLA DESDE UNA FUNCIÓN CON ACCIONES DE EMPAQUETADO Y DESEMPAQUETADO
Procedemos a desglosar lo que hemos hecho:
1.- Importamos con la sentencia import un módulo de la librería estándar de Python (stdlib, "std"de standard y "lib"de "library", esto es, una contracción de "standard library")) para traerla a nuestro código. En este caso, el módulo 'datetime', que nos permite trabajar con fechas.
2.- Instruimos una función definida por el usuario (def), es decir, codificada por nosotros mismos, que lleva por nombre tanteo_medio, y que llevará como argumentos sendas tuplas: 'partidos' y 'fecha_actual'.
3.- En esta línea de código procedemos al desempaquetado de una tupla, que no es otra cosa que establecer un número de variables separados por comas, en nuestro ejemplo, 'amistosos', 'liga' y 'competiciones_internacionales', esto es, una secuencia de tres variables cada una de las cuales tendrá su valor correspondiente, y que asignamos a la variable 'partidos' que pasamos en su momento como primer argumento de la función. Esta será nuestra tupla.
Y si no le hemos dicho a Python que 'partidos' es una tupla...¿Cómo sabe el intérprete que debe devolvernos una tupla? Lo explicamos más arriba: porque esta es la forma predeterminada que tiene Python de devolver una secuencia de datos si no especificamos el tipo de dato (lista, conjunto, etc.) en que queremos que nos la devuelva. Desde el punto de vista de cierta nomenclatura, obtendríamos una 3-tupla, es decir, una tupla compuesta de tres elementos. Así por ejemplo, una tupla como ésta: t = (1, 3.45, "hola", [1,2,3], "adiós", 77) sería una 6-tupla, ya que contiene 6 elementos (len(t) => 6).
4.- Aquí introducimos el retorno (return) de la función, es decir, el resultado de la ejecución de la función. Al colocar la devolución del retorno entre paréntesis, le estamos diciendo al intérprete que nos devuelva el resultado como una tupla. Deberá ser una 2-tupla porque pedimos que nos proporcione dos resultados: el primero, el valor obtenido de una expresión aritmética que pasa por introducir los valores de las tres variables de la tupla 'partidos', es decir, la suma de los valores de 'amistosos', 'liga' y 'competiciones_internacionales' dividida entre tres; y segundo, la fecha. Observemos que ambos se separan por comas.
5.- Como ya sabemos que vamos a obtener dos valores necesitaremos dos variables para almacenar cada uno de ellos. Así pues, declaramos sendas variables, 'media_de_tantos' y  'fecha' y les asignamos la llamada a la función (igual que  a nosotros nos llaman por nuestro nombre cuando pasan lista o en la consulta del médico, debemos llamar a las funciones por su nombre, para poderlas identificar. En nuestro ejemplo, tanteo-medio) pasando los valores correspondientes: tres enteros para 'amistosos, 'liga' y 'competiciones-internacionales' respectivamente, y un método del módulo datetime, datetime.date.today(), que nos devuelve un objeto de tipo date con la fecha actual.
Tengamos en cuenta que, del mismo modo que sucedía en 3., tenemos un nuevo desempaquetado que nos proporcionará dos variables que podremos llamar por separado para que nos muestren sus datos, tal y como haremos a continuación.
6. y 7.- Finalmente llamamos a las variables para que nos devuelvan los datos correspondientes

ACANTILADOS DEL MACIZO DE TENO, NOROESTE DE TENERIFE.
Añadamos un poquito más de teoría. En algunos lenguajes de programación como PHP, por ejemplo, existe el concepto de CONSTANTE. Una constante es un espacio de la memoria que se reserva mediante un referente (nombre) con el propósito de almacenar un dato o una colección de ellos. Hasta aquí es asimilable al concepto de variable. Sin embargo, a diferencia de ésta última, el valor almacenado en una constante no varía, sino que permanece así, constante, inmutable, a lo largo de la ejecución del programa. Como su nombre indica, una constante viene de perlas para almacenar un dato que sabemos que no se puede modificar, como el número pi, una constante física, el número de segundos que tiene un minuto, el peso atómico de un elemento químico, el radio de la órbita terrestre, etc.
¿Es una buena idea, verdad?
Pues bien: Python no la integra. Entonces, ¿qué es lo que en este lenguaje se asemeja más a la idea de constante? Una tupla. Pero, ¡ay!, como ya hemos aprendido en este capítulo, las tuplas adolecen de una practicidad limitada y bien poco podemos hacer con ellas.
Finalmente, vamos a proponer una nueva entrada que incida un poco más sobre las virtudes de la función print() en tanto que, como función "estrella", nunca estará de más repasar lo que ya sabemos y aprender alguna cosa más. Vamos a ello:

T1. A VUELTAS CON LA FUNCIÓN PRINT():


Toca ahora hacer unos pocos ejercicios. muy poquitos en esta ocasión, porque el tema tampoco da para mucho más. Así que vamos allá.


T4. BLOQUE DE EJERCICIOS 5. SOLUCIONES.


MONTAÑA DE GUAMA DESDE SANTIAGO DEL TEIDE, OESTE DE TENERIFE.

2 comentarios:

  1. Puede ser considerado un abuso, luego de semejante trabajo didáctico, pedirte si dispones de un listado resumido de "ordenes" de Python. Una especie de "ayuda memoria", por lo menos de las standard.
    Comprenderás, que con semejante caudal de "acciones" para realizar, uno las va leyendo del blogg, las entiende, pero a la hora de usarlas, no te vienen rápido a la mente. Por lo menos así pasa al principio.
    Busco en Google si a alguien se le ocurrió algo parecido, y no lo encuentro (todos te quieren enseñar Python, pero para eso te tengo a vos...).
    Gracias...
    JR

    ResponderEliminar
    Respuestas
    1. Hola, Maestro Yoda. Si haces clic sobre el libro abierto en la parte superior derecha, justo bajo el epígrafe HERRAMIENTAS Y UTILIDADES, abrirás un pequeño sitio web, subsidiario al blog (no dejes de navegar por él pues te proporcionará mucho material de ayuda para aumentar y mejorar tus conocimientos). En el menú seleccionas la última opción, HERRAMIENTAS, y encontrarás aquí como primera opción 'pythonlake'. Puedes hacer clic sobre el nombre para acceder al sitio: funciona como una chuleta con ejemplos. Es MUY ÚTIL y, además, te la puedes descargar. De todas maneras, aquí te dejo su dirección: http://pythonlake.com/. De nuevo, muchísimas gracias por confiar en nuestro blog. Feliz aprendizaje. Saludos.

      Eliminar