Café y Código

13. CRUD con listas y diccionarios: productos y expendedora 🛒

¿Qué es un CRUD?

Es el conjunto de operaciones típicas sobre datos: Crear (altas), Read (leer / listar), Update (modificar) y Delete (borrar). Aquí lo practicas primero guardando cada producto como una fila [nombre, precio] dentro de una lista, y después con un diccionario indexado por código (ideal para códigos de máquina expendedora).

1. Lista de productos: CRUD y cálculos

Cada elemento es [nombre, precio]. Los precios son números (por ejemplo float).

crud_lista.py
PYTHON
1 # Estado: lista de filas [nombre, precio]
2 productos = [
3 ["Agua", 1.0],
4 ["Galletas", 2.5],
5 ["Chocolate", 3.2],
6 ]
7
8 # --- CREATE ---
9 def agregar_producto(lista, nombre, precio):
10 lista.append([nombre.strip(), float(precio)])
11
12 # --- READ (listar) ---
13 def listar(lista):
14 if not lista:
15 print("(Sin productos)")
16 return
17 for nombre, precio in lista:
18 print(f" • {nombre}: {precio}")
19
20 # --- READ (buscar por nombre exacto) ---
21 def buscar_indice_por_nombre(lista, nombre):
22 nombre = nombre.strip().lower()
23 for i, fila in enumerate(lista):
24 if fila[0].lower() == nombre:
25 return i
26 return None
27
28 # --- UPDATE ---
29 def actualizar_precio(lista, nombre, nuevo_precio):
30 i = buscar_indice_por_nombre(lista, nombre)
31 if i is None:
32 print("Producto no encontrado.")
33 return
34 lista[i][1] = float(nuevo_precio)
35 print("Precio actualizado.")
36
37 # --- DELETE ---
38 def eliminar_por_nombre(lista, nombre):
39 i = buscar_indice_por_nombre(lista, nombre)
40 if i is None:
41 print("Producto no encontrado.")
42 return
43 eliminado = lista.pop(i)
44 print(f"Eliminado: {eliminado[0]}")
45
46 # --- Cálculos sobre precios ---
47 def producto_mas_caro(lista):
48 if not lista:
49 return None
50 return max(lista, key=lambda fila: fila[1])
51
52 def producto_mas_barato(lista):
53 if not lista:
54 return None
55 return min(lista, key=lambda fila: fila[1])
56
57 def suma_precios(lista):
58 return sum(fila[1] for fila in lista)
59
60 # Ejemplo de uso
61 listar(productos)
62 caro = producto_mas_caro(productos)
63 barato = producto_mas_barato(productos)
64 if caro:
65 print("¿Cuál es el mayor (más caro)?", caro[0], "→", caro[1])
66 if barato:
67 print("¿Cuál es el menor (más barato)?", barato[0], "→", barato[1])
68 print("Suma de todos los precios:", suma_precios(productos))

2. Mismo problema con diccionario (código → producto)

La clave puede ser el código de la repisa ("A1", "B2"…). El valor es un pequeño registro con nombre y precio. El CRUD usa dict[key], del, comprobar key in dict, etc.

crud_dict.py
PYTHON
1 catalogo = {
2 "A1": {"nombre": "Agua", "precio": 1.0},
3 "A2": {"nombre": "Galletas", "precio": 2.5},
4 "B1": {"nombre": "Chocolate", "precio": 3.2},
5 }
6
7 def listar_catalogo(cat):
8 for codigo in sorted(cat.keys()):
9 p = cat[codigo]
10 print(f" {codigo}: {p['nombre']} — {p['precio']}")
11
12 def agregar_o_reemplazar(cat, codigo, nombre, precio):
13 cat[codigo.strip().upper()] = {"nombre": nombre.strip(), "precio": float(precio)}
14
15 def actualizar_precio_cat(cat, codigo, nuevo_precio):
16 codigo = codigo.strip().upper()
17 if codigo not in cat:
18 print("Código no existe.")
19 return
20 cat[codigo]["precio"] = float(nuevo_precio)
21
22 def eliminar_codigo(cat, codigo):
23 codigo = codigo.strip().upper()
24 if codigo not in cat:
25 print("Código no existe.")
26 return
27 del cat[codigo]
28 print("Eliminado.")
29
30 def producto_mas_caro_cat(cat):
31 if not cat:
32 return None
33 # devuelve (codigo, datos)
34 return max(cat.items(), key=lambda item: item[1]["precio"])
35
36 def producto_mas_barato_cat(cat):
37 if not cat:
38 return None
39 return min(cat.items(), key=lambda item: item[1]["precio"])
40
41 def suma_precios_cat(cat):
42 return sum(p["precio"] for p in cat.values())
43
44 listar_catalogo(catalogo)
45 codigo_caro, datos_caro = producto_mas_caro_cat(catalogo)
46 print("Mayor precio:", datos_caro["nombre"], datos_caro["precio"])
47 codigo_barato, datos_barato = producto_mas_barato_cat(catalogo)
48 print("Menor precio:", datos_barato["nombre"], datos_barato["precio"])
49 print("Suma de precios:", suma_precios_cat(catalogo))

🐍 Reto rápido

Partiendo del ejemplo en lista, añade una función que devuelva el precio medio de todos los productos (suma de precios / cantidad). Evita división por cero si la lista está vacía.

👁️ Pista

Usa suma_precios(lista) / len(lista) solo cuando la lista no esté vacía (por ejemplo if lista: antes de dividir).

3. Máquina expendedora: comprar con saldo y stock

Combinas catálogo (código → nombre y precio) con otro diccionario de stock por código. El usuario ve el menú, introduce dinero y el código; restas stock y cobras el precio. Incluye validaciones básicas y try/except al leer números.

expendedora.py
PYTHON
1 def pedir_float(mensaje):
2 while True:
3 try:
4 return float(input(mensaje))
5 except ValueError:
6 print("Introduce un número válido.")
7
8 def mostrar_maquina(catalogo, stock):
9 print("\n--- Máquina expendedora ---")
10 for codigo in sorted(catalogo.keys()):
11 p = catalogo[codigo]
12 disp = stock.get(codigo, 0)
13 estado = f"(quedan {disp})" if disp > 0 else "(agotado)"
14 print(f" {codigo}: {p['nombre']} — {p['precio']} {estado}")
15
16 def comprar(catalogo, stock, saldo):
17 codigo = input("Código del producto: ").strip().upper()
18 if codigo not in catalogo:
19 print("Código inválido.")
20 return saldo, False
21 if stock.get(codigo, 0) < 1:
22 print("Producto agotado.")
23 return saldo, False
24 precio = catalogo[codigo]["precio"]
25 if saldo < precio:
26 print(f"Saldo insuficiente. Necesitas {precio}, tienes {saldo}.")
27 return saldo, False
28 stock[codigo] -= 1
29 saldo -= precio
30 print(f"¡Toma tu {catalogo[codigo]['nombre']}! Saldo restante: {round(saldo, 2)}")
31 return saldo, True
32
33 def main():
34 catalogo = {
35 "A1": {"nombre": "Agua", "precio": 1.0},
36 "A2": {"nombre": "Galletas", "precio": 2.5},
37 "B1": {"nombre": "Chocolate", "precio": 3.2},
38 }
39 stock = {"A1": 5, "A2": 3, "B1": 2}
40 saldo = pedir_float("Inserta dinero (saldo inicial): ")
41 while True:
42 mostrar_maquina(catalogo, stock)
43 print("\n[s] Seguir comprando [r] Recargar saldo [x] Salir")
44 op = input("Opción: ").strip().lower()
45 if op == "x":
46 print(f"Devolvemos cambio: {round(saldo, 2)}. ¡Gracias!")
47 break
48 if op == "r":
49 saldo += pedir_float("Cuánto añades: ")
50 continue
51 if op == "s" or op == "":
52 saldo, _ = comprar(catalogo, stock, saldo)
53
54 if __name__ == "__main__":
55 main()

Dato curioso: Primera versión pública en 1991; Guido van Rossum. Wikipedia

Ko-fi
Donaciones
Apoyá cafeycodigo con un café en Ko-fi. Colaboradores: insignia, muro y zona exclusiva.