Tuplas, sets y diccionarios
En esta guía (20)
Las listas no son la única colección de Python. En esta lección vas a conocer las tuplas (secuencias que no cambian), los sets (conjuntos sin repetidos) y los diccionarios (pares clave-valor), y vas a aprender a elegir cuál usar en cada caso. Los diccionarios se llevan la mayor parte: son, junto con las listas, la estructura que más vas a usar.
Tuplas
Una tupla es como una lista, pero inmutable: una vez creada no se le pueden agregar, quitar ni cambiar elementos. Se escribe con paréntesis:
punto = (3, 7)
fecha = (2026, 10, 13)
colores = ("rojo", "verde", "azul")
print(punto[0]) # 3
print(fecha[-1]) # 13
print(len(colores)) # 3
print("verde" in colores) # True
Índices, slicing, len, in y for funcionan igual que en las listas. Lo que no funciona es modificar:
>>> punto[0] = 10
TypeError: 'tuple' object does not support item assignment
Para qué sirve algo que no se puede cambiar
- Para datos que van juntos y tienen una estructura fija: una coordenada
(x, y), una fecha(año, mes, día), un registro("Ana", 34). - Para proteger datos: si algo no debería cambiar, una tupla lo garantiza.
- Como claves de diccionario (enseguida vas a ver por qué una lista no puede serlo).
Un detalle de sintaxis: una tupla de un solo elemento lleva una coma, (5,). Sin la coma, (5) es solo el número 5 entre paréntesis. En realidad, lo que crea la tupla es la coma, no los paréntesis: 3, 7 también es una tupla. Por eso, en la lección 2, precio = 3,5 no daba error: creaba la tupla (3, 5).
Desempaquetado
Podés asignar los elementos de una tupla (o lista) a varias variables a la vez:
fecha = (2026, 10, 13)
anio, mes, dia = fecha
print(f"{dia}/{mes}/{anio}") # 13/10/2026
La cantidad de variables tiene que coincidir con la cantidad de elementos. Si no, da ValueError.
El desempaquetado permite intercambiar dos variables en una línea:
a = 1
b = 2
a, b = b, a
print(a, b) # 2 1
Y es lo que ya usaste en la lección 4 con for i, tarea in enumerate(tareas): enumerate produce tuplas (índice, elemento) y el for las desempaqueta.
Cuando recorrés una lista de tuplas, el desempaquetado deja el código muy claro:
stock = [("yerba", 12), ("azúcar", 0), ("café", 5)]
for producto, cantidad in stock:
if cantidad == 0:
print(f"Sin stock: {producto}")
Sin stock: azúcar
Sets
Un set (conjunto) es una colección sin elementos repetidos y sin orden. Se escribe con llaves:
colores = {"rojo", "verde", "rojo", "azul", "verde"}
print(len(colores)) # 3
Los repetidos se descartan solos. Como no hay orden, no hay índices: colores[0] da error. Y el orden en que se imprimen puede variar.
Quitar repetidos
El uso más común: convertir una lista a set para eliminar duplicados (es el equivalente a DISTINCT si alguna vez usaste SQL).
visitas = ["ana", "bruno", "ana", "carla", "bruno", "ana"]
unicos = set(visitas)
print(len(unicos)) # 3
print(sorted(unicos)) # ['ana', 'bruno', 'carla']
sorted() acepta un set y devuelve una lista ordenada: es la forma de volver a tener orden.
Para crear un set vacío se usa set(), no {} (eso crea un diccionario vacío, como vas a ver enseguida).
Agregar, quitar y buscar
etiquetas = set()
etiquetas.add("urgente")
etiquetas.add("trabajo")
etiquetas.add("urgente") # ya estaba: no pasa nada
etiquetas.discard("personal") # no estaba: tampoco pasa nada
print(sorted(etiquetas)) # ['trabajo', 'urgente']
print("trabajo" in etiquetas) # True
Preguntar si algo está (in) es mucho más rápido en un set que en una lista, sobre todo cuando hay miles de elementos. La lista tiene que mirar uno por uno; el set va directo. Si vas a hacer muchas búsquedas, convertí a set.
Operaciones de conjuntos
curso_a = {"ana", "bruno", "carla", "diego"}
curso_b = {"carla", "diego", "elena"}
print(sorted(curso_a & curso_b)) # en los dos: ['carla', 'diego']
print(sorted(curso_a | curso_b)) # en alguno: ['ana', 'bruno', 'carla', 'diego', 'elena']
print(sorted(curso_a - curso_b)) # en A pero no en B: ['ana', 'bruno']
print(sorted(curso_a ^ curso_b)) # en uno solo: ['ana', 'bruno', 'elena']
| Operador | Método | Resultado |
|---|---|---|
a & b | a.intersection(b) | elementos en los dos |
a | b | a.union(b) | elementos en alguno |
a - b | a.difference(b) | elementos de a que no están en b |
a ^ b | a.symmetric_difference(b) | elementos que están en uno solo |
Si tenés dos listas y querés saber qué tienen en común, convertilas a sets y usá &: es más corto y más rápido que recorrer una lista preguntando si cada elemento está en la otra.
Diccionarios
Un diccionario guarda pares clave: valor. En vez de acceder por posición, accedés por clave:
precios = {"yerba": 3200, "azúcar": 1100, "café": 4500}
print(precios["café"]) # 4500
print(len(precios)) # 3
print("yerba" in precios) # True (in pregunta por las claves)
- Las claves son únicas. Suelen ser strings o números; tienen que ser inmutables (por eso una tupla puede ser clave y una lista no).
- Los valores pueden ser cualquier cosa: números, textos, listas, otros diccionarios.
- Los diccionarios mantienen el orden en que insertaste las claves.
Agregar, modificar y borrar
stock = {"yerba": 12, "café": 5}
stock["azúcar"] = 8 # clave nueva: se agrega
stock["café"] = 7 # clave existente: se reemplaza
print(stock) # {'yerba': 12, 'café': 7, 'azúcar': 8}
del stock["yerba"] # borra la clave
quitado = stock.pop("café") # borra y devuelve el valor
print(quitado, stock) # 7 {'azúcar': 8}
Leer una clave que puede no existir
Si pedís una clave que no está, da KeyError:
>>> precios["mate"]
KeyError: 'mate'
Para leer sin riesgo, usá get, que devuelve None (o el valor por defecto que le pases) si la clave no existe:
precios = {"yerba": 3200, "azúcar": 1100}
print(precios.get("mate")) # None
print(precios.get("mate", 0)) # 0
print(precios.get("yerba", 0)) # 3200
Recorrer un diccionario
precios = {"yerba": 3200, "azúcar": 1100, "café": 4500}
for producto in precios: # recorre las claves
print(producto, end=" ")
print()
for precio in precios.values(): # solo los valores
print(precio, end=" ")
print()
for producto, precio in precios.items(): # clave y valor (tuplas desempaquetadas)
print(f"{producto}: ${precio}")
yerba azúcar café
3200 1100 4500
yerba: $3200
azúcar: $1100
café: $4500
items() es el que más vas a usar: te da cada par como una tupla (clave, valor).
Contar con un diccionario
Un patrón clásico: contar cuántas veces aparece cada elemento.
votos = ["rojo", "azul", "rojo", "verde", "rojo", "azul"]
conteo = {}
for color in votos:
conteo[color] = conteo.get(color, 0) + 1
print(conteo) # {'rojo': 3, 'azul': 2, 'verde': 1}
La línea clave: conteo.get(color, 0) devuelve el conteo actual, o 0 si es la primera vez que aparece el color. Le sumás 1 y lo guardás. (En la lección 9 vas a ver Counter, una herramienta de la biblioteca estándar que hace esto en una línea.)
Agrupar y sumar
Una variante del mismo patrón: sumar valores por categoría.
gastos = [
("comida", 4500),
("transporte", 1200),
("comida", 3100),
("ocio", 6000),
("transporte", 800),
]
por_categoria = {}
for categoria, monto in gastos:
por_categoria[categoria] = por_categoria.get(categoria, 0) + monto
for categoria, total in por_categoria.items():
print(f"{categoria:<12}{total:>8}")
comida 7600
transporte 2000
ocio 6000
Diccionarios anidados y listas de diccionarios
Un diccionario puede representar un registro con varios campos, y una lista de diccionarios, una tabla:
alumnos = [
{"nombre": "Ana", "edad": 28, "notas": [8, 9, 7]},
{"nombre": "Bruno", "edad": 34, "notas": [6, 5, 8]},
]
for alumno in alumnos:
promedio = sum(alumno["notas"]) / len(alumno["notas"])
print(f"{alumno['nombre']}: {promedio:.1f}")
Ana: 8.0
Bruno: 6.3
Fijate que dentro de la f-string usamos comillas simples para la clave (alumno['nombre']) porque la f-string ya usa dobles.
Los diccionarios también se anidan:
config = {
"app": "gastos",
"usuario": {"nombre": "Ana", "moneda": "ARS"},
}
print(config["usuario"]["moneda"]) # ARS
print(config.get("tema", {}).get("color", "sin tema")) # sin tema
El segundo print muestra cómo leer un campo anidado que puede faltar sin romper: si "tema" no existe, get devuelve un diccionario vacío, y sobre ese el segundo get devuelve el valor por defecto.
Dict comprehensions
Igual que con las listas, podés armar un diccionario en una línea:
precios = {"yerba": 3200, "azúcar": 1100, "café": 4500}
con_aumento = {producto: round(p * 1.1) for producto, p in precios.items()}
print(con_aumento) # {'yerba': 3520, 'azúcar': 1210, 'café': 4950}
Cuál usar
| Necesitás... | Usá |
|---|---|
| una secuencia ordenada que va a cambiar | lista |
| un grupo fijo de valores que van juntos | tupla |
| elementos únicos, o preguntar rápido si algo está | set |
| buscar un valor a partir de una clave | diccionario |
| contar o agrupar por categoría | diccionario |
Errores comunes
KeyError: pediste una clave que no existe condic[clave]. Usádic.get(clave, valor_por_defecto)o preguntá antes conin.- Crear un set vacío con
{}. Eso es un diccionario vacío. El set vacío esset(). - Esperar orden en un set. No lo tiene. Si necesitás mostrarlo ordenado, usá
sorted(mi_set). - Usar una lista como clave de diccionario. Da
TypeError: unhashable type: 'list'. Convertila a tupla. - Olvidar la coma en una tupla de un elemento.
(5)es un número;(5,)es una tupla. - Desempaquetar con la cantidad equivocada de variables.
a, b = (1, 2, 3)daValueError: too many values to unpack.
Practicá
- Tenés las asistencias de dos semanas:
semana1 = ["ana", "bruno", "carla", "diego"]ysemana2 = ["carla", "elena", "ana", "fede"]. Mostrá, ordenados: quiénes vinieron las dos semanas, quiénes vinieron solo la primera y cuántas personas distintas asistieron en total. - Dado el diccionario
capitales = {"Argentina": "Buenos Aires", "Chile": "Santiago", "Uruguay": "Montevideo"}, armá el diccionario invertido (capital como clave, país como valor). - Dada esta lista de ventas como tuplas
(sucursal, monto), armá un diccionario con la cantidad de ventas y el total por sucursal, con la forma{"centro": {"cantidad": 2, "total": 2700}, ...}:ventas = [("centro", 1200), ("norte", 800), ("centro", 1500), ("sur", 400), ("norte", 950)] - Tenés un inventario
{"lapiceras": 30, "cuadernos": 12, "gomas": 0}. Escribí un programa que reciba un pedido (un diccionario como{"cuadernos": 5, "gomas": 2, "reglas": 1}) y, para cada producto, diga si se puede despachar o no (porque no hay suficiente o porque el producto no existe), descontando del inventario lo que sí se despacha.
Soluciones
Ejercicio 1:
semana1 = ["ana", "bruno", "carla", "diego"]
semana2 = ["carla", "elena", "ana", "fede"]
s1 = set(semana1)
s2 = set(semana2)
print("Las dos semanas:", sorted(s1 & s2))
print("Solo la primera:", sorted(s1 - s2))
print("Personas distintas:", len(s1 | s2))
Las dos semanas: ['ana', 'carla']
Solo la primera: ['bruno', 'diego']
Personas distintas: 6
Ejercicio 2:
capitales = {"Argentina": "Buenos Aires", "Chile": "Santiago", "Uruguay": "Montevideo"}
paises = {capital: pais for pais, capital in capitales.items()}
print(paises)
# {'Buenos Aires': 'Argentina', 'Santiago': 'Chile', 'Montevideo': 'Uruguay'}
Si dos claves tuvieran el mismo valor, al invertir se perdería una: las claves no se repiten.
Ejercicio 3:
ventas = [("centro", 1200), ("norte", 800), ("centro", 1500), ("sur", 400), ("norte", 950)]
resumen = {}
for sucursal, monto in ventas:
if sucursal not in resumen:
resumen[sucursal] = {"cantidad": 0, "total": 0}
resumen[sucursal]["cantidad"] += 1
resumen[sucursal]["total"] += monto
print(resumen)
# {'centro': {'cantidad': 2, 'total': 2700}, 'norte': {'cantidad': 2, 'total': 1750}, 'sur': {'cantidad': 1, 'total': 400}}
Ejercicio 4:
inventario = {"lapiceras": 30, "cuadernos": 12, "gomas": 0}
pedido = {"cuadernos": 5, "gomas": 2, "reglas": 1}
for producto, cantidad in pedido.items():
disponible = inventario.get(producto)
if disponible is None:
print(f"{producto}: no existe en el inventario")
elif disponible < cantidad:
print(f"{producto}: stock insuficiente (hay {disponible})")
else:
inventario[producto] -= cantidad
print(f"{producto}: despachado")
print(inventario)
cuadernos: despachado
gomas: stock insuficiente (hay 0)
reglas: no existe en el inventario
{'lapiceras': 30, 'cuadernos': 7, 'gomas': 0}
Para preguntar si algo es None se usa is None en vez de == None: es la forma recomendada, porque None es un valor único.
Resumen
- Las tuplas son secuencias inmutables, ideales para valores que van juntos; se desempaquetan con
a, b = tupla. - Los sets no tienen repetidos ni orden; sirven para deduplicar, buscar rápido con
iny combinar con&,|,-y^. - Los diccionarios guardan pares clave-valor;
dic[clave]daKeyErrorsi falta,dic.get(clave, defecto)no. items()recorre clave y valor a la vez.dic[k] = dic.get(k, 0) + 1es el patrón para contar; la misma idea sirve para sumar por categoría.- Listas de diccionarios y diccionarios anidados representan registros y estructuras más complejas.