← Principios básicos ETAPA 01 · 24 MIN

Funciones con un contrato

Dale a cada comportamiento un nombre, entradas, una salida y una promesa.

Abrir en el laboratorio ↗

AL TERMINAR, PODRÁS

  • Diferenciar un valor de retorno de lo que se imprime en pantalla
  • Escribir una función con entradas explícitas
  • Explicar precondiciones, postcondiciones y efectos secundarios
La función decide; quien la llama actúa. Su contrato nombra las entradas, el resultado y el error.

Descripción del diagrama: attempt: int → retry_delay() (entrada); retry_delay() → seconds: float (devuelve); retry_delay() → ValueError (lanza); seconds: float → sleep, log (quien llama actúa)

Una frontera útil

Una función empaqueta un comportamiento detrás de un nombre.

Su contrato explica qué entradas acepta, qué devuelve y qué estado modifica. Empieza con un cálculo puro, como la espera antes de un reintento: las mismas entradas producen la misma salida, sin llamadas de red ni estado oculto. Quien llama a la función puede usar el valor devuelto (return) en otro cálculo. print solo muestra un valor; no se lo devuelve a quien llamó.

Las funciones sin un return explícito devuelven None (el valor «nada» de Python).

Python
def retry_delay(attempt):
    if attempt < 0:
        raise ValueError("attempt must be nonnegative")
    return 60 if attempt >= 6 else 2 ** attempt

print(retry_delay(3))

Haz que las suposiciones se puedan revisar

Una precondición describe lo que debe cumplirse antes de que la función se ejecute.

Una postcondición describe lo que la función garantiza después. Nuestra función de espera exige un número de intentos no negativo y garantiza una espera de sesenta segundos como máximo. Compara el intento con seis antes de calcular 2 ** attempt, así que un número de intentos enorme nunca construye un número gigante.

Decide si una entrada inválida se rechaza, se convierte o se trata de forma especial; las suposiciones silenciosas suelen esconder errores. Las anotaciones de tipo (type hints) ayudan a las herramientas y a quien lee a entender la intención, pero las anotaciones normales de Python no validan nada mientras el programa corre. Un nombre de función preciso suele comunicar más que un comentario largo.

Separa las decisiones de los efectos

El código que decide si reintentar es más fácil de probar por separado del código con efectos secundarios (side effects: cambios que van más allá del valor devuelto), como esperar, escribir un archivo o enviar un correo.

Deja la decisión en una función pequeña y ejecuta el efecto en una frontera exterior. Eso no significa que cada línea necesite su propia función: extrae una frontera cuando nombre un concepto con significado o aísle una incertidumbre. Evita los argumentos por defecto mutables para estado de cada llamada: Python crea los objetos de los argumentos por defecto una sola vez, cuando se define la función, y eso puede compartir datos entre llamadas sin querer.

ERROR FRECUENTE

Un valor por defecto como jobs=[] comparte la misma lista entre llamadas. Usa None y crea una lista nueva dentro de la función cuando quieras estado independiente.

INTÉNTALO TÚ

Escribe eligible(status, attempts, limit) que devuelva un Boolean. Especifica su contrato y luego prueba trabajos completados, cero intentos e intentos exactamente iguales al límite.

COMPROBACIÓN DE RECUERDO / APLICA LA IDEA

Decide en el laboratorio.

El checkpoint de dos preguntas, tus notas y tu progreso guardado están en el laboratorio. Gratis y sin cuenta.

Abrir en el laboratorio ↗

CONÉCTALO CON RELAY

Extrae la decisión de reintento de Relay y el cálculo de la espera a funciones que no lean estado global.