Apariencia
📙 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.
*argsy**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)| Tipo | Cómo se pasa | Ventaja |
|---|---|---|
| Posicional | f("Ana") — por orden | corto |
| Keyword (por nombre) | f(nombre="Ana") | claro y sin depender del orden |
| Por defecto | se define en la función | el 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
*argsy**kwargs?" → Recogen argumentos variables:*argslos posicionales en una tupla,**kwargslos de nombre en un dict. Los nombresargs/kwargsson 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ón | Para qué te sirve |
|---|---|
| defaults | opciones de configuración de tu app (tema="oscuro") |
| keyword args | llamadas legibles: mover(fila=2, columna=0) como en .grid(row=, column=) |
**kwargs | helpers 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.0Ejercicio 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.5Ejercicio 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?
*argsen una tupla;**kwargsen 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=Noney se crea adentro.
4. ¿Dónde has usado keyword args en CustomTkinter?
En todos lados:
CTkButton(app, text=..., command=...),.grid(row=..., column=...).
📎 Apuntes relacionados
➡️ Siguiente
Clase 10 · Scope — variables locales/globales y el gotcha del lambda en bucles.