1.4 · Funciones, argumentos y alcance

Nivel 1 · Fundamentos del lenguaje

1.4Funciones, argumentos y alcance

Objetivo: definir funciones con def, gestionar argumentos, valores por defecto, *args/**kwargs, return y el alcance de las variables.
Tiempo estimado: 14 min · lectura autónoma · Si solo tienes 5 min: lee «Lo esencial en 30s» + el esquema.

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.

Error frecuente de interpretación: « print en la función basta » o « un valor por defecto [] es práctico ». No. print muestra en pantalla pero no transmite nada: sin return, la llamada vale None y el resultado no es ni almacenable ni calculable. Y el valor por defecto mutable se crea una sola vez: def f(items=[]) acumula entre llamadas — None + creación dentro, siempre.
Funciones sanas Un trabajo, valores seguros, alcance local Un trabajo (verbo) def +return, no printValores (inmutables) None, no[]; *args/**kwargsAlcance (local) Argumentos deentrada, return de salida
Un trabajo, valores seguros, alcance local
Versión en texto del esquema (SEO / lectores de pantalla / traducción): 1) Definir: Nabil escribe def moyenne(*notes) una sola vez en lugar de cuatro copiar-pegar — nombre verbo, una responsabilidad, return. 2) Asegurar: valores por defecto inmutables (None + creación dentro), *args para el número variable, **kwargs para las opciones. 3) Aislar: variables locales, todo entra por argumentos, todo sale por return — ninguna global. Lección: una función = interfaz explícita, espacio aislado, resultado devuelto.

🔎 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

  1. Escribe una función saluer(nom) que devuelva (return) « Bonjour, {nom} ! ». Llama con distintos nombres y muestra el resultado.
  2. Añade un parámetro por defecto: saluer(nom, politesse="Bonjour"). Llama con y sin el segundo argumento.
  3. 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.
  4. Ilustra el alcance: crea una variable en una función e intenta acceder desde fuera (NameError). Concluye sobre local frente a global.
Creas funciones reutilizables con argumentos, valores por defecto y return, y entiendes el alcance local de las variables.

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.

Lista de salida de la sección
  • Defino funciones con parámetros, valor seguro, return y *args.
  • Respeto el alcance local — ninguna global modificada.
  • Distingo print (mostrar) de return (transmitir).
Autoevaluación 1-5: ¿mis funciones reciben todo en parámetros?¿cada resultado reutilizado sale por return?

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...).

Comprueba tu comprensión

¿Cuánto vale la llamada de una función sin return?

Recursos adicionales (opcional, para ir más allá)

Examen del nivel 1Preguntas inéditas y más difíciles para validar tus conocimientos