Skip to content

📙 Clase 09 — Parámetros y argumentos

Fase 2 · Funciones y código organizado ⬅️ Volver al índice de clases

🎯 Qué aprendí

  • Argumentos posicionales vs por nombre (keyword) y valores por defecto.
  • *args y **kwargs: funciones con cantidad variable de argumentos.
  • El gotcha del default mutable y por qué CustomTkinter funciona a punta de kwargs.

📖 PARTE TEÓRICA

🏷️ 1. Posicionales, por nombre y por defecto

python
def saludar(nombre, saludo="Hola"):     # 'saludo' tiene valor POR DEFECTO
    return f"{saludo}, {nombre}"

print(saludar("Ana"))                    # Hola, Ana      (usa el default)
print(saludar("Ana", saludo="Buenas"))   # Buenas, Ana    (lo sobreescribo)
print(saludar(saludo="Chau", nombre="Luis"))  # Chau, Luis (por nombre: orden libre)
TipoCómo se pasaVentaja
Posicionalf("Ana") — por ordencorto
Keyword (por nombre)f(nombre="Ana")claro y sin depender del orden
Por defectose define en la funciónel que llama puede omitirlo

⚠️ Los parámetros con default van después de los que no lo tienen: def f(a, b=1) ✅ · def f(a=1, b) 💥 SyntaxError.

📚 2. *args: cantidad variable de posicionales

*args recoge todos los argumentos posicionales "extra" en una tupla.

python
def sumar_todo(*args):        # recibe los que sean
    return sum(args)

print(sumar_todo(1, 2, 3))    # 6
print(sumar_todo(5))          # 5

🗂️ 3. **kwargs: cantidad variable por nombre

**kwargs recoge los argumentos con nombre "extra" en un diccionario (¡Clase 04!).

python
def ficha(**kwargs):
    return kwargs

print(ficha(nombre="Ana", edad=30))    # {'nombre': 'Ana', 'edad': 30}

def demo(*args, **kwargs):             # los dos juntos (en ese orden)
    return args, kwargs

print(demo(1, 2, color="rojo"))        # ((1, 2), {'color': 'rojo'})
llamada:  demo( 1, 2,  color="rojo" )
                └┬─┘   └─────┬─────┘
        args = (1, 2)   kwargs = {"color": "rojo"}

🧪 Tip de entrevista: "¿Qué son *args y **kwargs?" → Recogen argumentos variables: *args los posicionales en una tupla, **kwargs los de nombre en un dict. Los nombres args/kwargs son convención; los asteriscos son lo que importa.

💣 4. EL gotcha: default mutable

Nunca uses una lista (o dict) como valor por defecto: se crea una sola vez y se comparte entre todas las llamadas.

python
def agregar_mal(x, lista=[]):     # ¡la MISMA lista para siempre!
    lista.append(x)
    return lista

print(agregar_mal(1))    # [1]
print(agregar_mal(2))    # [1, 2]   ← ¡¿y este 1?! se acumuló de la llamada anterior

def agregar_bien(x, lista=None):  # el patrón correcto
    if lista is None:
        lista = []                # lista NUEVA en cada llamada
    lista.append(x)
    return lista

print(agregar_bien(1))   # [1]
print(agregar_bien(2))   # [2]    ← ahora sí

⚠️ Es de las preguntas de entrevista más famosas de Python. Regla: defaults solo con inmutables (None, números, strings, tuplas); para mutables, None + crear adentro.


🖥️ EN TU APP DE ESCRITORIO

CustomTkinter entero funciona con **kwargs. Cada widget acepta decenas de opciones y tú pasas solo las que quieres, por nombre:

python
boton = ctk.CTkButton(
    app,
    text="Guardar",          # ← todos estos son kwargs
    command=guardar,
    fg_color="#3776ab",
    width=120,
)

Y tú puedes crear funciones fábrica con defaults para no repetir estilo:

python
def crear_boton(padre, texto, accion, **extra):
    """Botón con el estilo de MI app; 'extra' permite personalizar puntualmente."""
    return ctk.CTkButton(padre, text=texto, command=accion,
                         corner_radius=8, **extra)

b1 = crear_boton(app, "Guardar", guardar)
b2 = crear_boton(app, "Borrar", borrar, fg_color="red")   # extra kwarg → override
PatrónPara qué te sirve
defaultsopciones de configuración de tu app (tema="oscuro")
keyword argsllamadas legibles: mover(fila=2, columna=0) como en .grid(row=, column=)
**kwargshelpers que envuelven widgets sin re-declarar cada opción

💡 widget.grid(row=1, column=0, padx=10) — llevas semanas usando keyword args sin saberlo.


🗄️ CON BASE DE DATOS (caso de uso)

Los parámetros con nombre hacen las funciones de datos autoexplicativas:

python
def buscar_contactos(con, texto="", limite=50):
    return con.execute(
        "SELECT nombre, tel FROM contactos WHERE nombre LIKE ? LIMIT ?",
        (f"%{texto}%", limite),
    ).fetchall()

buscar_contactos(con)                        # todos (hasta 50)
buscar_contactos(con, texto="an")            # filtrados
buscar_contactos(con, limite=10)             # solo cambio el límite

🏋️ EJERCICIOS CON SOLUCIÓN

Ejercicio 1 — Precio con descuento

Escribe precio_final(precio, descuento=0) que devuelva el precio con el descuento (en %) aplicado. Pruébala con y sin descuento.

Ver solución
python
def precio_final(precio, descuento=0):
    return precio * (1 - descuento / 100)

print(precio_final(100))                 # 100.0  (sin descuento)
print(precio_final(100, descuento=25))   # 75.0

Ejercicio 2 — Promedio de lo que sea

Escribe promedio(*args) que funcione con 2, 3 o 10 números.

Ver solución
python
def promedio(*args):
    return sum(args) / len(args)

print(promedio(4, 8))          # 6.0
print(promedio(1, 2, 3, 4))    # 2.5

Ejercicio 3 — Etiqueta configurable

Escribe describir(**kwargs) que devuelva un texto "clave=valor, clave=valor" con lo que reciba (pista: .items() y join).

Ver solución
python
def describir(**kwargs):
    return ", ".join(f"{k}={v}" for k, v in kwargs.items())

print(describir(nombre="Ana", rol="admin"))   # nombre=Ana, rol=admin

❓ Preguntas y respuestas (autoevaluación)

1. ¿Qué diferencia hay entre f("Ana") y f(nombre="Ana")?

El primero es posicional (por orden); el segundo es keyword (por nombre, orden libre).

2. ¿En qué estructura recoge *args y en cuál **kwargs?

*args en una tupla; **kwargs en un diccionario.

3. ¿Por qué def f(x, lista=[]) es un bug esperando pasar?

El default se crea una sola vez: todas las llamadas comparten la misma lista y se acumulan datos. Se usa lista=None y se crea adentro.

4. ¿Dónde has usado keyword args en CustomTkinter?

En todos lados: CTkButton(app, text=..., command=...), .grid(row=..., column=...).


📎 Apuntes relacionados

  • Los dicts detrás de **kwargsClase 04
  • El default mutable conecta con el aliasing → Clase 01

➡️ Siguiente

Clase 10 · Scope — variables locales/globales y el gotcha del lambda en bucles.