Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Parámetros y Argumentos

Un procedimiento que siempre hace lo mismo es poco más que una macro con pretensiones. Un robot que solo corta madera de exactamente 1 metro no sirve de nada en un almacén donde los pedidos varían. Lo que hace útil a una función es que acepta variables. Eso es lo que controlan los parámetros y los argumentos.

Parámetros: Los Requisitos (El Formulario)

Piensa en el SOP como un formulario impreso: tiene huecos en blanco con etiquetas. Cuando defines la función, esos huecos son los Parámetros. No son datos todavía, son promesas de que llegará un dato.

# 'producto' y 'cantidad' son los huecos a llenar
def generar_pedido(producto: str, cantidad: int) -> None:
    print(f"Pedido recibido: {cantidad} cajas de {producto}")

Argumentos: Los Datos Reales (El Contenido)

El formulario impreso no hace nada solo. Alguien tiene que llenarlo con información concreta antes de mandarlo. Cuando ejecutas la función y le pasas valores reales, esos valores son los Argumentos.

# "Tornillos" y 500 son los datos reales
generar_pedido("Tornillos", 500)

La distinción es más útil de lo que parece. Parámetro es vocabulario de la definición; argumento es vocabulario del uso. Confundirlos genera conversaciones raras cuando describes errores.

Conector eléctrico: el PARÁMETRO (receptáculo, tipo: string) recibe el ARGUMENTO (conector, valor: ‘Ana’). Así fluyen los datos de la llamada a la definición

Fig. 9.4: El parámetro recibe al argumento.

Formas de Llenar el Formulario

Tienes dos maneras de pasar los datos:

  1. Por Posición (Confianza): Asumes que el primero va al primero y el segundo al segundo. generar_pedido("Tornillos", 500)

  2. Por Nombre (Explícito): Etiquetas cada dato. Es más seguro y claro. El orden no importa. generar_pedido(cantidad=500, producto="Tornillos")

Nota: Si tu función tiene más de dos parámetros, usa siempre argumentos por nombre: te evitarás confusiones.

Valores por Defecto (Huecos ya Rellenados)

Algunos huecos del formulario casi siempre llevan el mismo valor. En vez de obligar a escribirlo cada vez, le das un valor por defecto en la definición: si quien llama no lo pasa, se usa ese. Si lo pasa, manda el suyo.

def generar_pedido(producto: str, cantidad: int = 1) -> None:
    print(f"Pedido: {cantidad} cajas de {producto}")

generar_pedido("Tornillos")        # cantidad usa el defecto: 1
generar_pedido("Tornillos", 500)   # cantidad llega como 500

Una regla del lenguaje: los parámetros con valor por defecto van al final, después de los obligatorios. def f(a=1, b) es un error de sintaxis; def f(b, a=1) es correcto.

¡Ojo!: nunca uses una lista (u otro mutable) como valor por defecto, como def f(items=[]). Esa lista se crea una sola vez y queda compartida entre todas las llamadas, así que se va llenando sola de una a otra:

def registrar_mal(nuevo, items=[]):
    items.append(nuevo)
    return items

print(registrar_mal("Tornillos"))  # ['Tornillos']
print(registrar_mal("Tuercas"))    # ['Tornillos', 'Tuercas']  ← ¡no empezó vacía!

Cada llamada hereda la basura de la anterior, aunque tú no le hayas pasado nada. Si necesitas una lista vacía por defecto, usa None y créala dentro:

def registrar(nuevo: str, items: list | None = None) -> list:
    if items is None:
        items = []
    items.append(nuevo)
    return items

La revisión va con el is None del Capítulo 6, no con un atajo tipo items = items or []: una lista vacía que quien llama pasó a propósito también cuenta como “falsa”, y el or la reemplazaría en silencio.

Cuando el Argumento es un Estante Completo

El Capítulo 5 te enseñó el aliasing: dos etiquetas pueden apuntar al mismo estante. Ahora conecta ese cable con las funciones, porque pasar una lista a una función es exactamente eso: la función no recibe una copia, recibe otra etiqueta a TU estante.

def marcar_revision(pendientes: list) -> None:
    pendientes.append("REVISAR")   # esto muta el estante ORIGINAL

lote = ["Tornillos", "Tuercas"]
marcar_revision(lote)
print(lote)   # ['Tornillos', 'Tuercas', 'REVISAR'] ← tu lista cambió

A veces es justo lo que quieres (así trabaja inventario.append(...) en el proyecto final). Pero cuando NO lo quieres, hay dos defensas: pasarle una copia (marcar_revision(lote.copy())) o, mejor, que la función devuelva una lista nueva en vez de mutar la que recibió, como hace eliminar_producto en el proyecto final. Los números, textos y tuplas están a salvo de esto: son inmutables, la función no puede alterarte el original.

Existe Más Vocabulario (y Queda Fuera)

Cuando leas código ajeno verás firmas como def f(*args, **kwargs) o llamadas tipo print(*lista). Son mecanismos para aceptar cantidades variables de argumentos. Funcionan, tienen su lugar, y este libro no los cubre: para todo lo que construimos aquí, los parámetros explícitos son más claros. Solo debes saber que existen para que no te desconcierten.