1. Faro

Nivel 6 · Depuración: la rebaja cambió nuestros precios de lista

La solicitud

De Thomas Whitaker, Director de Merchandising

“Ejecuté el script que pone los precios de la rebaja del 20% del fin de semana, y ahora nuestra lista de precios regulares también muestra los precios de rebaja. Las columnas de «antes» y «después» son idénticas. ¿Puedes arreglarlo para que los precios de lista se queden como estaban?”

Tu objetivo

Corrige apply_markdown para que devuelva una lista nueva de precios reducidos pct por ciento (cada uno redondeado a 2) sin cambiar la lista que recibe. Asigna a result un diccionario con dos claves: 'list' (el list_prices original, sin cambios) y 'sale' (los precios rebajados).

  • Guarda un dict en resultpendiente

Tu código

Python

Cargando el editor…

    ResultadoPresiona Ejecutar para ver el tuyo

    Mote revisa tu resultado

    Presiona Ejecutar. Cada fila que cumple el objetivo se vuelve una luciérnaga en tu linterna.

    La lección

    Dos nombres, una lista

    Cuando llamas a apply_markdown(list_prices, 20), Python no copia la lista. El parámetro prices pasa a ser un segundo nombre para el mismo objeto lista. Todo lo que la función haga a prices[i] también le ocurre a list_prices:

    a = [369.00, 159.00]
    b = a            # no copy: two names for one list
    b[0] = 295.20
    a                # [295.2, 159.0]

    Los números y los strings no se pueden cambiar en el sitio, así que con ellos esto nunca da problemas. Las listas y los diccionarios sí, y de ahí viene la sorpresa. El bucle del starter con range(len(prices)) recorre las posiciones 0 a 4 y escribe cada precio de rebaja de vuelta en la lista de quien llama, por eso las columnas «list» y «sale» salieron idénticas. No saltó ningún error; el daño solo se vio en los números.

    Devuelve una lista nueva

    El patrón seguro es una función que lee su entrada y construye una salida nueva. Una list comprehension lo hace en una línea:

    def apply_markdown(prices, pct):
        return [round(p * (1 - pct / 100), 2) for p in prices]

    Después de la corrección, list_prices sigue conteniendo 369.00, 159.00, 72.99, 27.99 y 44.99, y los precios de rebaja son 295.20, 127.20, 58.39, 22.39 y 35.99. Puedes volver a ejecutar la función con 25% y obtener una segunda respuesta correcta, porque la primera vez no se sobrescribió nada.

    Si de verdad necesitas un bucle, copia primero con prices = list(prices) al principio de la función y luego edita la copia. Escribir una lista nueva suele ser más sencillo.

    Cómo detectar este tipo de error

    El síntoma es siempre el mismo: datos que no tocaste cambian después de llamar a una función. Dos comprobaciones rápidas lo encuentran. Imprime la entrada antes y después de la llamada, y busca dentro de la función asignaciones sobre un argumento (prices[i] = ..., row["x"] = ...) o métodos que lo cambian en el sitio, como .append(), .sort() o .pop().

    Errores comunes

    • Devolver prices.copy() al final. El bucle ya había cambiado el original.
    • Escribir sale_prices = list_prices antes de la llamada y pensar que es una copia. Es un segundo nombre.
    • Usar list_prices.sort() dentro de una función de informe, lo que reordena la lista de quien llama para siempre.

    Elige qué puede ejecutarse en este sitio. Puedes cambiarlo cuando quieras desde "Configurar cookies", al pie de cada página.