Tiza Las materias del CBC
Practicar →

Pensamiento Computacional (090) · Unidad 4 — Estructuras de datos

Tuplas

Una tupla es una lista que no se puede modificar. Sirve justamente para eso: dejar claro que ese conjunto de datos no cambia.

Practicar este tema →7 ejercicios que te corrigen paso a paso · gratis, sin cuenta

La explicación

Van con paréntesis

punto = (3, 5)
punto[0]   → 3
len(punto)  → 2

Se indexa y se recorre igual que una lista. La única diferencia es que punto[0] = 9 da error: las tuplas son inmutables.

Para qué sirve algo que no se puede cambiar

Justamente para eso. Una tupla dice "esto es un dato compuesto que no se toca": las coordenadas de un punto, una fecha, el ancho y alto de una imagen. Si más adelante alguien intenta modificarla, Python avisa en vez de dejarlo pasar.

Como regla: lista para una colección de cosas del mismo tipo que puede crecer (las notas de un curso), tupla para un dato con partes fijas (un par de coordenadas).

Empaquetar y desempaquetar

punto = (3, 5)       # empaquetar
x, y = punto         # desempaquetar: x vale 3, y vale 5

Esto ya lo venís usando sin saberlo. Cuando una función hace return a // b, a % b está devolviendo una tupla, y c, r = dividir(7, 2) la está desempaquetando.

De ahí también sale el intercambio en una línea del tema 2.1:

a, b = b, a

La derecha arma la tupla (b, a) y la izquierda la desempaqueta. Por eso no hace falta variable auxiliar: la tupla la hace de intermediaria.

Una tupla de un solo elemento

t = (5)     → esto es el número 5, no una tupla
t = (5,)    → esto sí es una tupla de un elemento

La coma es lo que hace la tupla, no el paréntesis. Es una rareza de Python que conviene conocer porque el error que produce es desconcertante.

Convertir

list((1, 2, 3))   → [1, 2, 3]
tuple([1, 2, 3])  → (1, 2, 3)

Para qué se usan de verdad: devolver más de un valor

Éste es el uso que aparece en cada programa un poco largo, y casi nunca se lo presenta como «tupla»:

def extremos(xs):
    return min(xs), max(xs)

r = extremos([4, 8, 15, 16, 23, 42])  → (4, 42)
mn, mx = extremos([4, 8, 15, 16, 23, 42])  → mn = 4, mx = 42

Una función devuelve un valor, siempre. Lo que pasa con return a, b es que ese único valor es una tupla, y el desempaquetado del otro lado la reparte. Por eso conviene tener el tema claro aunque nunca escribas un paréntesis a propósito: lo estás usando igual.

Lo que una lista no puede hacer

Al no poder cambiar, una tupla sirve de clave de diccionario y una lista no:

d = {(0, 0): "origen", (1, 2): "punto"}   → funciona
d = {[0, 0]: "origen"}                    → TypeError: unhashable type: 'list'
Inmutable no significa congelado del todo. Lo que no se puede cambiar es qué objetos están adentro de la tupla, no el estado interno de esos objetos. Si una tupla contiene una lista, la lista sigue siendo modificable:
t = (1, [2, 3])
t[1].append(4)   → t ahora es (1, [2, 3, 4])
t[0] = 9           → TypeError: 'tuple' object does not support item assignment
La segunda línea funciona y la tercera no. Es exactamente la distinción entre modificar y reasignar del tema 4.2, y es de lo que más se pregunta en la evaluación de código.
Ejemplo resuelto

Una función tiene que recibir una lista de puntos (x, y) y devolver cuántos están en el primer cuadrante (los dos valores positivos).

Cada punto es una tupla, así que se puede desempaquetar directamente en el for:

def en_primer_cuadrante(puntos):
    cuenta = 0
    for x, y in puntos:
        if x > 0 and y > 0:
            cuenta = cuenta + 1
    return cuenta

Con [(1, 2), (-3, 4), (5, 6)]: el primero cuenta, el segundo no (x es negativo), el tercero sí. Devuelve 2.

Fijate el for x, y in puntos. En cada vuelta agarra una tupla y la desempaqueta sola en dos variables. La alternativa sería for p in puntos: y después usar p[0] y p[1], que funciona igual pero se lee mucho peor: x e y dicen qué son, p[0] no.

Por qué tupla y no lista para cada punto. Un punto tiene exactamente dos coordenadas y no va a crecer. La tupla deja eso escrito, y de paso evita que alguien le haga append por error.

Control: probá con un punto en el eje, como (0, 5). Con > no cuenta, que es lo correcto: el origen y los ejes no son parte de ningún cuadrante.

La variante que suelen pedir a continuación: que además de contar, la función devuelva cuántos quedaron sobre los ejes. Dos resultados, un solo return:
return en_cuadrante, en_eje
y del lado de afuera dentro, ejes = contar(puntos). No hace falta ninguna estructura nueva: return a, b arma una tupla y el desempaquetado la reparte en dos variables con nombre.

El control que cierra la variante: los dos números tienen que sumar el total de puntos de la lista. Si suman de menos, hay un punto que no entró en ninguna de las dos ramas — casi siempre por haber usado > en un lado y >= en el otro.

Dónde se cae la mayoría

Hasta acá la explicación. La práctica es la otra mitad: 7 ejercicios de este tema, en cuatro niveles, que no te dicen sólo si está bien al final sino que te corrigen en cada paso y te explican por qué. Además trae una animación que muestra la idea en movimiento.

Practicar Tuplas →

Ver todos los temas de Pensamiento Computacional