La sentencia return finaliza la ejecución de una función y entrega un valor al código que la llamó. Es una de las ideas más importantes para escribir programas modulares: una función calcula, transforma o decide algo, y luego devuelve un resultado que puede reutilizarse.
return no es lo mismo que print
print muestra información en la pantalla. return entrega un valor. Una función que solo imprime puede ser difícil de combinar con otras operaciones.
def sumar_mal(a, b):
print(a + b)
def sumar(a, b):
return a + b
resultado = sumar(4, 6)
print(resultado * 2)Para dominar la estructura completa, revisa la guía de funciones en Python.
Qué ocurre al ejecutar return
Cuando Python encuentra return, abandona la función inmediatamente. Las líneas posteriores no se ejecutan:
def clasificar(numero):
if numero < 0:
return "negativo"
if numero == 0:
return "cero"
return "positivo"Este estilo de retornos tempranos puede reducir niveles de indentación y hacer la lógica más clara.
Funciones que no incluyen return
Si una función termina sin return, Python devuelve None implícitamente:
def registrar(nombre):
print(f"Usuario: {nombre}")
valor = registrar("Elena")
print(valor) # NoneMuchos errores aparecen cuando el programador espera un número, texto o lista, pero recibe None. Comprueba siempre el contrato de la función.
Devolver varios valores
Python permite escribir varios valores separados por comas:
def estadisticas(valores):
minimo = min(valores)
maximo = max(valores)
promedio = sum(valores) / len(valores)
return minimo, maximo, promedio
menor, mayor, media = estadisticas([2, 4, 8])En realidad, se devuelve una tupla. El desempaquetado facilita asignar cada componente a una variable.
Devolver estructuras claras
Cuando hay muchos resultados, una tupla puede resultar poco descriptiva. Es mejor devolver un diccionario, una dataclass o un objeto con campos nombrados. Esto evita depender de posiciones misteriosas y facilita ampliar el resultado.
def resumen(valores):
return {
"cantidad": len(valores),
"total": sum(valores),
"promedio": sum(valores) / len(valores),
}return dentro de bucles
Un return dentro de un bucle termina tanto el bucle como la función:
def buscar_par(numeros):
for numero in numeros:
if numero % 2 == 0:
return numero
return NoneSi necesitas procesar todos los elementos, no devuelvas dentro del primer ciclo. Un error de indentación puede provocar que la función termine demasiado pronto.
Validación y excepciones
No todos los casos inválidos deben representarse con None. A veces una excepción expresa mejor el problema:
def dividir(a, b):
if b == 0:
raise ValueError("El divisor no puede ser cero")
return a / bUsa None cuando la ausencia de resultado sea esperada. Usa excepciones cuando el llamador haya incumplido una condición o el cálculo no pueda realizarse.
Type hints para resultados
Las anotaciones indican qué devuelve una función:
def nombre_completo(nombre: str, apellido: str) -> str:
return f"{nombre} {apellido}"Los type hints en Python ayudan a detectar retornos incompatibles antes de ejecutar el programa. No impiden que Python devuelva otro tipo, pero mejoran documentación y análisis estático.
return en funciones con *args y **kwargs
Las funciones flexibles también deben definir con claridad su resultado. La guía de *args y **kwargs muestra cómo recibir parámetros variables. El hecho de aceptar muchos argumentos no justifica devolver datos ambiguos.
return en decoradores
Un wrapper debe devolver el valor de la función original, a menos que el decorador tenga un propósito diferente:
from functools import wraps
def registrar(funcion):
@wraps(funcion)
def wrapper(*args, **kwargs):
print("Llamada registrada")
return funcion(*args, **kwargs)
return wrapperOlvidar ese return hace que la función decorada produzca None. Puedes profundizar en la guía de decoradores en Python.
Funciones generadoras
Una función que utiliza yield se comporta como generador. En ese contexto, return detiene la iteración. Aunque puede incluir un valor interno asociado a StopIteration, normalmente se usa solo para terminar. No confundas una función generadora con una función que construye y devuelve una lista completa.
Buenas prácticas
Intenta que una función tenga un propósito claro y un tipo de retorno predecible. Evita mezclar en distintas ramas valores incompatibles como números, listas y cadenas. Documenta los casos en que puede devolver None. Usa retornos tempranos para manejar errores simples, pero no fragmentes la lógica con demasiadas salidas.
La referencia oficial de la sentencia return describe su comportamiento formal, mientras que el tutorial oficial de funciones ofrece ejemplos para principiantes. Comprender return transforma funciones aisladas en componentes reutilizables que pueden combinarse en programas mayores.
Resultados mutables
Una función puede devolver listas o diccionarios, pero quien recibe el objeto puede modificarlo. Esto es correcto cuando la función crea un resultado nuevo. Debes tener cuidado si devuelve una referencia interna de una clase, porque el código externo podría alterar el estado sin pasar por métodos de validación. En esos casos conviene devolver una copia, una tupla inmutable o una vista controlada.
Consistencia entre ramas
Una función con varias condiciones debería devolver resultados compatibles. Si una rama devuelve un diccionario y otra una cadena de error, cada llamador necesitará lógica especial. Es preferible devolver siempre la misma estructura o lanzar una excepción. Esta consistencia mejora los type hints, las pruebas y el mantenimiento.
def obtener_producto(producto_id):
if producto_id <= 0:
raise ValueError("ID inválido")
return {"id": producto_id, "nombre": "Producto"}Pruebas del valor devuelto
No pruebes solo lo que aparece en pantalla. Guarda el resultado y compáralo con el valor esperado. Incluye casos normales, límites y errores. Las funciones puras, que dependen únicamente de sus argumentos y devuelven un resultado sin modificar estado externo, suelen ser especialmente fáciles de probar y reutilizar.






