1.4Funciones, argumentos y alcance
Lo esencial en 30 segundos
- Función = un trabajo, un nombre verbo: def calculer_tva(prix_ht): + return — mostrar (print) no es devolver.
- Valores por defecto inmutables: def f(items=None) y luego creación dentro — nunca def f(items=[]) que sobrevive entre llamadas.
- Local primero, global nunca: datos en argumentos, resultado por return — *args/**kwargs para la flexibilidad.
Minicaso guiado — Nabil factoriza sus cálculos en Argel
Nabil calcula la media de las puntuaciones en cuatro lugares de su script con el mismo copiar-pegar — y cuando la regla cambia (ignorar los ceros), olvida dos lugares: uno de cada cuatro informes es falso. Crea una función moyenne(*notes) que recibe todo en parámetros y devuelve el resultado: un solo lugar que corregir. De paso, corrige un def ajouter(x, items=[]) que acumulaba entre llamadas (None + creación dentro) y sustituye un print por un return. Los cuatro informes vuelven a ser correctos de golpe.
Continuación del caso 1.1-1.3 — Nabil pasa de la repetición a la reutilización.
1. Una función = un trabajo, un nombre verbo
Una función es un bloque nombrado y reutilizable: def calculer_tva(prix_ht): — nombre verbo + snake_case, una responsabilidad, return el resultado. Sin return, la función devuelve None: print muestra, return transmite — el print no sustituye al return. Es el principio DRY (no te repitas).
Nabil sustituye sus cuatro copiar-pegar de media por moyenne(*notes): un solo lugar que corregir cuando la regla cambia, cuatro informes correctos.
2. Argumentos, valores por defecto y alcance
Los parámetros se declaran en la definición, los argumentos se pasan en la llamada; los valores por defecto van después de los obligatorios (def saluer(nom, politesse="Bonjour")). Trampa famosa: def f(items=[]) — la lista sobrevive entre llamadas, escribe def f(items=None). *args recoge valores, **kwargs pares nombre=valor. Alcance: una variable creada en la función es local (NameError fuera) — pasa por argumentos, recupera por return.
Nabil corrige su valor por defecto mutable en None, añade moyenne(*notes) para 2 y luego 5 notas, y constata el NameError de una variable local accedida desde fuera: local contra global, decidido.
🔎 Ejemplo concreto — 🔎 Ejemplo concreto — La trampa de la lista por defecto
El bug famoso, como Nabil con sus medias.
def ajouter(x, items=None):
items = items if items is not None else []
items.append(x)
return items
print(ajouter(1)) # [1]
print(ajouter(2)) # [2]: sin más sorpresas
def moyenne(*notes):
return sum(notes) / len(notes)
print(moyenne(12, 15, 9))
Lectura: el valor por defecto mutable se crea una sola vez — None + creación dentro lo evita.
Lección: *args recoge un número variable de argumentos; return hace el resultado reutilizable.
Vocabulario de la sección
- Función / def
- Bloque de código nombrado y reutilizable, definido con def nom(paramètres):. Llamado por nom(arguments). Nombre verbo, una responsabilidad (DRY).
Ejemplo sencillo: La moyenne(*notes) única de Nabil, llamada cuatro veces.
Lo que no es: el mismo cálculo copiado-pegado en cuatro lugares.
Reflejo: cálculo repetido dos veces = función.
- Parámetro / argumento
- El parámetro es la variable declarada en la definición; el argumento es el valor real pasado en la llamada. Los valores por defecto van después de los obligatorios.
Ejemplo sencillo: El politesse="Bonjour" de saluer(nom) en casa de Nabil.
Lo que no es: un valor por defecto mutable [] compartido entre llamadas.
Reflejo: valores por defecto inmutables (None), nunca [] o {}.
- return
- Devuelve un valor a la salida de la función y pone fin a su ejecución. Sin return, la función devuelve None. print muestra, return transmite.
Ejemplo sencillo: La media devuelta por Nabil, almacenada y luego mostrada.
Lo que no es: una función que hace print sin return, inutilizable en cálculo.
Reflejo: resultado por reutilizar = return, siempre.
- Alcance (scope)
- Zona de visibilidad de una variable. Una variable creada en una función es local: no existe fuera (NameError).
Ejemplo sencillo: La variable local de Nabil, inaccesible fuera.
Lo que no es: modificar una global con global en lugar de un parámetro.
Reflejo: ¿necesitas un dato? parámetro; ¿necesitas el resultado? return.
- *args / **kwargs
- Permiten recibir un número variable de argumentos: *args (tupla de valores), **kwargs (diccionario de pares nombre=valor).
Ejemplo sencillo: La moyenne(*notes) de Nabil con 2 y luego 5 notas.
Lo que no es: cinco parámetros opcionales interminables en lugar de *args.
Reflejo: número desconocido = *args; opciones nombradas = **kwargs.
En la práctica — En la práctica — Definir y llamar funciones
- Escribe una función saluer(nom) que devuelva (return) « Bonjour, {nom} ! ». Llama con distintos nombres y muestra el resultado.
- Añade un parámetro por defecto: saluer(nom, politesse="Bonjour"). Llama con y sin el segundo argumento.
- Escribe una función moyenne(*notes) que acepte un número variable de notas y devuelva su media. Prueba con 2, y luego 5 notas.
- Ilustra el alcance: crea una variable en una función e intenta acceder desde fuera (NameError). Concluye sobre local frente a global.
Guion listo para decir — rechazar el print en lugar del return (30 s)
« Propongo que esta función devuelva el resultado con return en lugar de mostrarlo: así podemos almacenarlo, testearlo y reutilizarlo. El print no transmite nada — la llamada vale None y el cálculo siguiente falla. »
Para decir en revisión de código; muestra la llamada almacenada antes/después.
Modelo copiar-pegar — funciones sanas (return, valor seguro, *args)
def saluer(nom, politesse="Hola"):
return f"{politesse}, {nom} !"
print(saluer("Nabil"))
print(saluer("Yasmine", politesse="Hola"))
def moyenne(*notes):
return sum(notes) / len(notes)
print(moyenne(12, 15))
print(moyenne(10, 14, 16, 8, 12))
def ajouter(x, items=None):
items = items if items is not None else []
items.append(x)
return items
Medias en Argel
Como Nabil: una sola función moyenne(*notes) — la regla cambia una vez, cuatro informes correctos.
Dato externo por usar
Pasarlo en parámetro explícito: la firma documenta la necesidad, la función sigue testeable aisladamente.
Valor por defecto
El politesse="Bonjour" por defecto: la llamada simple cubre el caso corriente, la llamada completa el caso particular.
Número variable
*notes para 2 y luego 5 notas, **options para los ajustes nombrados: la firma sigue corta y flexible.
✓ Buenas prácticas
- Un verbo, un trabajo, un return — nunca un print en su lugar.
- Valores por defecto inmutables (None, no [] ni {}).
- Datos en argumentos, nunca en global.
✗ Errores frecuentes
- Hacer print en lugar de return (llamada que vale None).
- Escribir un valor por defecto mutable ([] o {}) que sobrevive entre llamadas.
- Usar global para modificar fuera en lugar de un parámetro.
Puntos clave
- Una función (def) agrupa un código reutilizable: principio DRY — nombre verbo, una responsabilidad.
- return devuelve un resultado reutilizable; sin él, la función devuelve None (print no sustituye a return).
- Argumentos por defecto, *args y **kwargs ofrecen flexibilidad — solo valores inmutables.
- Una variable definida en una función es local: invisible fuera — argumentos de entrada, return de salida.
Desafío 48h — aplica mañana
Extrae un cálculo duplicado de tu script en función (modelo anterior): parámetros explícitos, return, valor seguro. Sustituye un print por un return y prueba con 2 y luego 5 argumentos. 25 minutos bastan.
- Defino funciones con parámetros, valor seguro, return y *args.
- Respeto el alcance local — ninguna global modificada.
- Distingo print (mostrar) de return (transmitir).
Preguntas frecuentes
¿Qué diferencia hay entre print() y return en una función?
print() muestra en pantalla pero no transmite nada al resto del programa. return devuelve un valor explotable (almacenable, calculable). Una función que « print » sin « return » solo sirve para mostrar; para reutilizar el resultado hace falta return — si no la llamada vale None.
¿Para qué sirven *args y **kwargs en concreto?
Hacen flexible una función sobre el número de argumentos. *args recoge valores posicionales en tupla (útil para una media de un número desconocido de notas); **kwargs recoge pares clave=valor en diccionario (útil para opciones nombradas como sep, titre...).
¿Cuánto vale la llamada de una función sin return?