En este video vamos a introducir el tipo de datos que Python llama "tuplas" y que en el fondo están muy relacionados con las listas. Como parte de esto, estudiaremos las características básicas de la estructura y discutiremos la importancia de que las tuplas sean inmutables. Después pasaremos a explicar los principales casos de uso para las tuplas y la operación de desempaquetado, que es tremendamente útil en muchos escenarios. Empecemos recordando que Python tiene un tipo llamado "list", que representa estructuras de datos lineales en las cuales cada elemento se identifica con un índice o posición. A diferencia de otros lenguajes, estas listas son mutables. Esto quiere decir que, después de que construyamos una lista, podemos modificar sus elementos, quitarlos o agregar nuevos usando métodos como "append". Las tuplas son muy similares a las listas. También son estructuras de datos lineales donde los elementos se identifican con un índice o posición, pero son inmutables. Es decir que los valores que guardemos en una tupla cuando la construyamos no se podrán cambiar más adelante. De hecho, si intentamos modificar un valor, obtendremos un error que nos advierte que las tuplas no soportan la asignación de valores. La pregunta natural en este punto es: ¿Para qué necesitamos tuplas si ya tenemos listas? Para responder a esta pregunta, recordemos que la mayoría de tipos de datos que hemos estudiado tienen un solo valor asociado. Un "int" es un solo número entero, un "float" es un solo número decimal y un "bool" es un solo valor de verdad. Entonces, ¿qué tipo de datos podríamos usar si necesitamos representar algo que naturalmente tenga una cantidad fija de valores y que esa cantidad sea mayor a uno? Por ejemplo, si queremos representar las coordenadas de un punto en el espacio, siempre vamos a necesitar tres flotantes para representar la posición con respecto a los ejes "x", "y" y "z". Podríamos usar un diccionario con las tres llaves "x", "y" y "z", pero, por un lado, eso no nos garantiza que nadie vaya a agregar o quitar una llave y, por otro lado, el código se complicaría más de lo necesario. Podríamos también utilizar una lista, pero igual que en un diccionario alguien podría modificarla por error y dejar dos o cuatro o cinco valores en lugar de los tres que necesitamos. Peor aún, alguien podría reemplazar uno de nuestros números decimales por una cadena de caracteres y terminaríamos con un error cuando alguien intentara calcular algo a partir de las coordenadas del punto. Gracias a la inmutabilidad podemos garantizar que una tupla siempre tendrá la la cantidad de elementos correcta y que esos elementos serán también de los tipos correctos, porque una vez haya creado una tupla en mi memoria sus elementos ya no podrán cambiar. Veamos ahora cómo se usan las tuplas en Python, concentrándonos en las diferencias que tienen con respecto a las listas. Lo primero que hay que notar es que las tuplas se crean igual que una lista, pero usando paréntesis redondos en lugar de cuadrados en el momento de la creación. En el ejemplo de la derecha estamos creando una nueva tupla con tres valores y, como ya sabemos, esos valores no los podremos cambiar más adelante. Finalmente, recordemos que, si hubiéramos querido crear una lista y no una tupla, solo habríamos tenido que usar paréntesis cuadrados. En realidad, los paréntesis son opcionales para crear una tupla. Python soporta una operación llamada "empaquetado", que no es más que asignarle a una variable una serie de valores separados por coma. El resultado de esta operación es una tupla con los valores que teníamos a la derecha de la asignación. Como veremos en los siguientes ejemplos, esta operación de empaquetado y la operación opuesta de desempaquetado son muy utilizadas y son muy útiles para escribir código corto y fácil de entender. Como estamos apenas conociendo las tuplas, en los ejemplos anteriores solo hemos construido tuplas con enteros. Sin embargo, las tuplas pueden ser tan complejas como nosotros queramos. Podemos tener tuplas dentro de tuplas, tuplas con listas, listas con tuplas o cualquier combinación que se nos ocurra. También podemos tener tuplas que tengan elementos de tipos diferentes, pero en ese caso tenemos que poner muchísima atención a las posiciones donde queden los valores. En el ejemplo de la diapositiva estamos creando una tupla que representa un rectángulo. El primer elemento de la tupla es también una tupla que representa las coordenadas "x" y "y" de la esquina del rectángulo. El segundo elemento de la tupla rectángulo también es una tupla con dos elementos que representa el tamaño de la figura, expresadas como el ancho y el alto. El tercer elemento del rectángulo: su color, representado con una cadena de caracteres. Para completar la explicación sobre la creación de tuplas hablemos de dos casos especiales. El primero son las tuplas vacías, las cuales se crean usando solo los paréntesis. En realidad, una tupla vacía no es de mucha utilidad, pero no está de más saber que podrían existir. El segundo son las tuplas unitarias o con un solo elemento. Tampoco son de muchísima utilidad, pero es importante saber que para crear una tupla con un solo elemento es obligatorio incluir una coma después del elemento. Es decir que si queremos una tupla solo con el número cinco debemos escribir: cinco "coma" dentro de los paréntesis. Si no incluimos la coma, Python pensará que es un entero y no una tupla unitaria. Para consultar el contenido de una tupla tenemos a nuestra disposición los mismos mecanismos que para consultar el contenido de una lista. Para extraer el valor de una posición particular podemos usar el operador de indexación con los paréntesis cuadrados. Al igual que en una lista, las posiciones están numeradas a partir del cero y obtendremos un error si intentamos utilizar una posición que sea mayor al tamaño de la tupla. También podemos utilizar las operaciones de "slicing" para extraer un fragmento de una tupla. Como vemos en la diapositiva, si usamos "slicing" para extraer los elementos de una tupla, obtendremos también una tupla. Al igual que con las listas, también podemos utilizar números negativos para referirnos a posiciones contadas a partir de la última posición. Finalmente, la función "len" es la que debemos usar para conocer la cantidad de elementos en una tupla, al igual que en las listas. Resolvamos la siguiente pregunta para revisar lo que estamos aprendiendo. Volvamos ahora al tema del empaquetado y el desempaquetado. Como vimos antes, si le asignamos a una variable un conjunto de valores separados por coma, Python construirá una tupla. La expresión opuesta ocurre cuando le asignamos una tupla a un conjunto de variables separados por coma. Esto se ve un poco extraño porque siempre hemos puesto una única variable a la izquierda del igual. Lo que hace Python, en este caso, es que toma cada uno de los elementos de la tupla y se lo asigna a una de las variables. Con lo que tenemos que tener mucho cuidado es con tener la misma cantidad de variables que elementos en la tupla. Por ejemplo, en la diapositiva estamos desempaquetado la tupla rectángulo y dejando sus componentes en tres variables. Si la tupla hubiera tenido más o menos elementos, el programa habría fallado con un error. Si tuviéramos una lista, esto podría haber tenido muchos problemas, pero como las tuplas son inmutables podemos confiar en que nadie le agregó o quitó elementos a rectángulo después de que lo creamos. Para concluir este video, veamos ahora dos usos muy frecuentes de las tuplas. El primero es como retorno de una función. Como sabemos, una función puede retornar solo un valor, aunque hay casos en los que nos gustaría retornar varios. Por ejemplo, sería útil tener una función que, dada una lista de números, retorne el valor máximo, el mínimo, el promedio y la desviación estándar sin tener que hacer múltiples recorridos. Retornando una tupla podríamos lograr esto. En la diapositiva tenemos un ejemplo un poco más sencillo. A partir de la información del rectángulo, la función que estamos definiendo retorna una tupla que tiene el área y el perímetro del rectángulo. En la última línea del programa invocamos la función y además desempaquetamos el resultado en dos variables separadas. El segundo uso frecuente de las tuplas es para simplificar y reducir los parámetros de una función. En lugar de tener muchos parámetros, usando una tupla podemos organizarlos y posiblemente facilitar el uso. En la diapositiva tenemos un ejemplo que ilustra esto. En lugar de tener una función que calcula la distancia entre dos puntos usando cuatro números, es decir, las coordenadas "x" uno, "y" uno y "x" dos, "y" dos de los dos puntos, tenemos una función que recibe dos puntos, donde cada uno está representado por una tupla con su coordenada "x" y "y". En la invocación a la función que mostramos abajo podemos ver que el llamado es bastante sencillo y no es fácil confundir o intercambiar números, como pasa en otros casos. Por ejemplo, si fueran puntos en el espacio representados por posiciones en "x", "y" y "z" y la función que calcula la distancia no recibiera tuplas, tendríamos que usar seis parámetros para hacer la invocación. Veamos ahora una pregunta para revisar que todo esté claro.