Cuando construyes funciones o métodos en Python, no siempre sabes de antemano cuántos datos vas a recibir. Dominar el uso de args y kwargs te permite escribir código flexible que acepta una cantidad variable de argumentos, ya sea sin nombre o con nombre. A continuación se explican estas técnicas con ejemplos prácticos que incluyen funciones y clases.
¿Cómo funcionan los args para recibir argumentos sin nombre?
Los args (precedidos por un asterisco *) permiten que una función reciba un número indefinido de argumentos no posicionales, es decir, sin asignarlos a una variable específica. Internamente, Python los almacena en una tupla, lo que significa que son inmutables [01:36].
El nombre args es una convención; podrías usar cualquier otro, pero por buenas prácticas se mantiene este. Veamos un ejemplo sencillo:
Cada invocación pasa una cantidad distinta de parámetros y la función los procesa sin problemas [02:25]. La clave está en el asterisco antes del nombre: le indica a Python que agrupe todo lo que llegue en una tupla.
¿Qué son los kwargs y cuándo se usan argumentos con nombre?
Los kwargs (keyword arguments) se declaran con doble asterisco** y reciben argumentos posicionales con nombre, es decir, pares clave=valor. Python los almacena en un diccionario [03:22].
python
def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_info(name="Carlos", age=30, city="Bogotá")
Si después necesitas agregar más datos, como country="Colombia", la función los acepta sin modificar su definición [04:40]. Esto resulta muy útil cuando la estructura de información puede crecer o variar entre llamadas.
¿Cómo combinar parámetros directos, args y kwargs en una clase?
Es posible mezclar las tres técnicas en un mismo constructor o método. Se define primero el parámetro directo, luego *args y finalmente **kwargs [05:17].
python
class Employee:
def init(self, name, *args, **kwargs):
self.name = name
self.skills = args
self.details = kwargs
"Python", "Java" y "C++" van a args como tupla porque no tienen nombre.
age=30 y city="Bogotá" van a kwargs como diccionario porque sí tienen nombre [06:55].
Esta separación permite que cada empleado tenga un número diferente de skills y de detalles adicionales.
¿Qué es el desempaquetado de args y kwargs?
Cuando la información ya existe en una variable externa, puedes desempaquetarla al pasarla a una función [08:05].
¿Cómo desempaquetar una lista con un solo asterisco?
python
def add(a, b, c):
return a + b + c
values = (1, 2, 3)
print(add(*values)) # 6
El asterisco antes de values extrae cada elemento de la tupla y lo coloca como argumento independiente.
¿Cómo desempaquetar un diccionario con doble asterisco?
python
def show_info(name, age):
print(f"{name} tiene {age} años")
data = {"name": "Carlos", "age": 30}
show_info(**data)
El doble asterisco descompone el diccionario en pares clave=valor que coinciden con los parámetros de la función [09:00].
¿Cuándo elegir args y cuándo kwargs?
Usa *args cuando recibas valores sin etiqueta, como una lista de precios o puntuaciones.
Usa **kwargs cuando necesites pares clave-valor, como configuraciones, descuentos o metadatos.
Combínalos con parámetros directos cuando haya datos que siempre sean obligatorios.
Como reto, intenta crear una función que reciba una cantidad variable de precios con *args y un descuento opcional con **kwargs, aplicando ese descuento a los productos indicados. La práctica te ayudará a identificar rápidamente cuál técnica usar en cada situación. ¿Qué combinación te resultó más útil? Comparte tu solución en los comentarios.
classVenta:def__init__(self,*args,**kwargs): self.prices = args
self.discounts = kwargs
defcalcular_total(self)->int:print("Calculando totales")if self.discounts:#comprobamos si un descuento fue pasado como kwargfor key, value in self.discounts.items():#iteramos las claves y valores del diccionario kwarg discount = value #asignamos el valor encontrado en 'value' a discountreturnprint(f"La suma total aplicando un descuento del {discount} % es: {sum(self.prices)*((100- discount)/100)}")else:returnprint(f"La suma de total es: {sum(self.prices)}")#retornamos la suma de los 'args' si no hay descuento.venta1 = Venta(200,300,400, discount=10)venta2 = Venta(800,200)venta1.calcular_total()venta2.calcular_total()
Excelente, super clean el código
excelente aportacion
Los parámetros \*args y \*\*kwargs en Python son utilizados para pasar un número variable de argumentos a una función. Esto es útil cuando no se conoce de antemano cuántos argumentos se van a pasar a la función. Vamos a desglosar cada uno de ellos:
### \*args
- **Significado**: \*args permite pasar un número variable de argumentos posicionales a una función. Cuando se utiliza, Python agrupa todos los argumentos adicionales que se pasan a la función en una tupla.
- **Uso**: Se usa cuando no se sabe cuántos argumentos se van a pasar a la función.
#### Ejemplo de \*args
defsumar(\*args):  total = 0  for numero in args:  total += numero  return totalresultado = sumar(1,2,3,4,5)print(resultado)# Salida: 15
En este ejemplo, la función sumar puede aceptar cualquier cantidad de argumentos, y todos ellos se suman.
### \*\*kwargs
- **Significado**: \*\*kwargs permite pasar un número variable de argumentos nombrados (keyword arguments) a una función. Python agrupa todos los argumentos adicionales en un diccionario.
- **Uso**: Se utiliza cuando se quieren pasar un número variable de argumentos con nombre.
#### Ejemplo de \*\*kwargs
def imprimir\_info(\*\*kwargs):  for clave, valor in kwargs.items():  print(f"{clave}: {valor}")imprimir\_info(nombre="Juan", edad=30, ciudad="Bogotá")
Salida:
nombre:Juanedad:30ciudad:Bogotá
En este caso, la función imprimir\_info recibe argumentos nombrados que se almacenan en un diccionario kwargs. Luego, se itera sobre ese diccionario para imprimir cada clave y su correspondiente valor.
### Uso combinado de \*args y \*\*kwargs
Puedes usar \*args y \*\*kwargs en la misma función. Sin embargo, siempre debes poner \*args antes de \*\*kwargs.
Argumentos posicionales:(1,2,3)Argumentos con nombre:{'nombre':'Juan','edad':30}
### Resumen
- **\*args**: Para argumentos posicionales variables, se agrupan en una tupla.
- **\*\*kwargs**: Para argumentos nombrados variables, se agrupan en un diccionario.
Ambos son herramientas poderosas que permiten a las funciones ser más flexibles y adaptables a diferentes situaciones.
Gracias por tu aporte
defcalcular_total(*precios:float,**opciones)->float:"""
Calcula el total de una lista variable de precios.
Si se proporciona un descuento (porcentaje) como argumento con nombre,
lo aplica al total.
"""# 1. Calcular el total bruto total =sum(precios)print(f"🧾 Total sin descuento: ${total:.2f}")# 2. Verificar si hay descuento opcional descuento = opciones.get("descuento",0)# por defecto 0%if descuento: total = total *(1- descuento /100)print(f"💸 Descuento aplicado: {descuento}%")print(f"✅ Total final: ${total:.2f}")return total
# 🧪 Ejemplos de usoif __name__ =="__main__":# Caso 1: Sin descuento calcular_total(10.0,25.5,40.0)# Caso 2: Con descuento calcular_total(100.0,50.0,75.0, descuento=10)# Caso 3: Otro descuento calcular_total(200.0,100.0,50.0, descuento=25)
definfo_productos(*args:int,**kwargs): total =sum(args)print(f"Precio total de los productos: {total}")if"descuento"in kwargs: porcentaje = kwargs["descuento"] monto_descuento = total * porcentaje /100 total_condescuento = total - monto_descuento
print(f" Tu descuento es de {porcentaje}%, el total es de {total_condescuento}")else:print("No hay descuento")info_productos(23000,56000,46000,32000,78000,12000, descuento=30)
'''
Crear una función que reciba una cantidad variable de productos y sus precios.1.Calcula el total.2.Aplica un descuento opcional si se proporciona un argumento de descuento.'''
classSales: def __init__(self,name: str,*args,**kwargs): #Atributos de la clase de ventas, nombre y argumentos y keyword arguments
self.name= name
self.prices= args
self.discounts= kwargs
def adding_product(self): #Función que calcula la suma de productos y si hay descuentos los aplica igualmente
print("Calculo del total por ventas: ")if self.discounts:for key, value in self.discounts.items(): discount = value
returnprint(f"La suma total de {self.name} aplicando un descuento del {discount} % es: {sum(self.prices) * ((100 - discount) / 100)}")returnprint(f"La suma total de {self.name} es: {sum(self.prices)}")#Creación de dos ventas con sus datos
sale1 =Sales('Daniela',200,400,2000, discount=10)sale2 =Sales('Yesica Giraldo Tique',200,400,2000,5000000,40000, discount=10)#Activa la funcion de adicionar productos 1 y 2sale1.adding_product()sale2.adding_product()```'''Crear una función que reciba una cantidad variable de productos y sus precios.1.Calcula el total.2.Aplica un descuento opcional si se proporciona un argumento de descuento. '''class Sales: def \_\_init\_\_ (self, name: str, \*args, \*\*kwargs): #Atributos de la clase de ventas, nombre y argumentos y keyword arguments self.name = name self.prices = args self.discounts = kwargs def adding\_product(self): #Función que calcula la suma de productos y si hay descuentos los aplica igualmente print("Calculo del total por ventas: ") if self.discounts: for key, value in self.discounts.items(): discount = value return print(f"La suma total de {self.name} aplicando un descuento del {discount} % es: {sum(self.prices) \* ((100 - discount) / 100)}") return print(f"La suma total de {self.name} es: {sum(self.prices)}") #Creación de dos ventas con sus datos sale1 = Sales('Daniela', 200, 400, 2000, discount=10)sale2 = Sales('YesicaGiraldoTique',200,400,2000,5000000,40000, discount=10)\#Activa la funcion de adicionar productos 1 y 2sale1.adding\_product()sale2.adding\_product()
"""
Crear una función que reciba una cantidad variable de productos y sus precios,
calcule el total y aplique un descuento opcional si se proporciona como un argumento con nombre.
1. Usar args para recibir una lista de precios
2. Usar kwargs para aceptar un descuento opcional y aplicarlo al total.
"""defcalcular_total(*args,**kwargs)->float: total =0# Variable para llevar el total de la orden# Recorrer la lista de diccionarios de producto, cantidad y preciofor p in args[0]: total +=(p['cant']* p['precio'])#Validar si hay descuentofor key, value in kwargs.items():print(f'{key}: {value}')if key =='descuento': total = total -(total * value/100)return total
# Ejemplo de uso# Creo una orden, que sería un diccionario de productos con sus cantidades y preciosorden =[{'nombre':'lapiz','cant':2,'precio':3},{'nombre':'cuaderno','cant':5,'precio':5},{'nombre':'compas','cant':1,'precio':10},{'nombre':'regla','cant':1,'precio':2},{'nombre':'sacapunta','cant':2,'precio':5}]# Orden con descuento del 10%print("El total de la compra con descuento es:", calcular_total(orden, descuento=10))# Orden sin descuentoprint("El total de la compra sin descuento es:", calcular_total(orden))```"""Crear una función que reciba una cantidad variable de productos y sus precios, calcule el total y aplique un descuento opcional si se proporciona como un argumento con nombre.
1\. Usar args para recibir una lista de precios
2\. Usar kwargs para aceptar un descuento opcional y aplicarlo al total.
""" def calcular\_total(\*args, \*\*kwargs)->float: total =0# Variable para llevar el total de la orden # Recorrer la lista de diccionarios de producto, cantidad y precio for p in args\[0]: total += (p\['cant'] \* p\['precio']) #Validar si hay descuento for key, value in kwargs.items(): print(f'{key}: {value}') if key == 'descuento': total = total - (total \* value/100) return total\# Ejemplo de uso
\# Creo una orden, que sería un diccionario de productos con sus cantidades y preciosorden = \[{'nombre':'lapiz','cant':2,'precio':3},{'nombre':'cuaderno','cant':5,'precio':5},{'nombre':'compas','cant':1,'precio':10},{'nombre':'regla','cant':1,'precio':2},{'nombre':'sacapunta','cant':2,'precio':5}]\# Orden con descuento del10%print("El total de la compra con descuento es:", calcular\_total(orden, descuento=10))\# Orden sin descuentoprint("El total de la compra sin descuento es:", calcular\_total(orden))
classfactura_productos:'''
Calcular el valor a pagar de una factura por una compra
recibiendo lista de productos, con nombre, cantidad y precio
El descuento es opcional y aplicado a toda la compra
Parametros:args: descuento
kwargs: productos como lista de diccionarios
Retorna:El valor a pagar con el descuento aplicado
'''
def __init__(self,*args,**kwargs): self.descuento= args
self.productos= kwargs
def total_factura(self)-> float: total =0.0for product inproductos: total += product['precio']*product['cantidad']print("Sub Total:", total)if descuento >0: total -= total*descuento/100return total
def print_productos(self):print("Lista de la compra.")for producto inproductos:print(f"{producto['nombre']} Cantidad:{producto['cantidad']} \
Precio:${producto['precio']} Subtotal:${producto['cantidad']*producto['precio']}")productos =[{"nombre":"jabòn","precio":5000,"cantidad":2,},{"nombre":"servilletas","precio":2000,"cantidad":1,},{"nombre":"papitas","precio":3000,"cantidad":3,}]#descuento en porcentaje
descuento =10aPagar =factura_productos(descuento, productos)aPagar.print_productos()print(f"Total a pagar: ${aPagar.total_factura()} descuento:{descuento}%")```classfactura\_productos:''' Calcular el valor a pagar de una factura por una compra recibiendo lista de productos, con nombre, cantidad y precio El descuento es opcional y aplicado a toda la compra
 Parametros: args: descuento kwargs: productos como lista de diccionarios
 Retorna:El valor a pagar con el descuento aplicado ''' def \_\_init\_\_(self, \*args, \*\*kwargs):*self*.descuento= args *self*.productos= kwargs
  def total\_factura(self)-> float: total =0.0for product inproductos: total += product\['precio']\*product\['cantidad']print("Sub Total:", total)if descuento >0: total -= total\*descuento/100return total def print\_productos(self):print("Lista de la compra.")for producto inproductos:print(f"{producto\['nombre']} Cantidad:{producto\['cantidad']} \ Precio:${producto\['precio']} Subtotal:${producto\['cantidad']\*producto\['precio']}")productos = \[{"nombre":"jabòn","precio":5000,"cantidad":2,},{"nombre":"servilletas","precio":2000,"cantidad":1,},{"nombre":"papitas","precio":3000,"cantidad":3,}]*#descuento en porcentaje*descuento =10aPagar = factura\_productos(descuento, productos)aPagar.print\_productos()print(f"Total a pagar: ${aPagar.total\_factura()} descuento:{descuento}%")
defcalcular_total_detallado(*args,**kwargs):"""
Calcula el total de una lista de precios y muestra un desglose detallado.
:param args: lista variable de precios
:param kwargs: puede incluir 'descuento' (porcentaje, ej: 10 para 10%)
:return: total final con descuento aplicado si existe
"""print("🧾 DESGLOSE DE COMPRA")print("-"*30)# Validar y mostrar productos total =0for i, precio inenumerate(args, start=1):if precio <0:raise ValueError(f"El precio del producto {i} no puede ser negativo")print(f"Producto {i}: ${precio:.2f}") total += precio
print("-"*30)print(f"Subtotal: ${total:.2f}")# Aplicar descuento si existe descuento = kwargs.get('descuento',0)if descuento:if descuento <0or descuento >100:raise ValueError("El descuento debe estar entre 0 y 100") monto_descuento = total *(descuento /100) total_final = total - monto_descuento
print(f"Descuento aplicado: {descuento}%")print(f"Monto de descuento: -${monto_descuento:.2f}")else: total_final = total
print("Sin descuento aplicado")print("-"*30)print(f"TOTAL A PAGAR: ${total_final:.2f}")return total_final
# Ejemplo de usocalcular_total_detallado(100,250,50, descuento=15)
Jhon, puedes usar una extensión de Visual Studio Code, para tomar las capturas mucho más limpias:
CodeSnap - Visual Studio Marketplace
classProduct: def __init__(self, name, price): self.name= name
self.price= price
def calculate_total(*args,**kwargs)-> float: total =0for product inargs: total += product.priceif'discount'inkwargs: total = total -(total * kwargs['discount'])return total
product1 =Product('laptop',1000)product2 =Product('smartphone',500)product3 =Product('tablet',300)print(calculate_total(product1, product2, product3, discount=0.1))
Mi respuesta al ejercicio, aún estoy intentando comprender bien la validación de datos:
defcalcular_total(*args:float,**kwargs:float)->float:# Calculamos la suma inicial de todos los precios pasados por args total_bruto =sum(args)# Obtenemos el descuento de kwargs. Si no existe, usamos 0 por defecto. descuento_porcentual = kwargs.get("descuento",0)# Validamos que el descuento sea un número coherenteifnotisinstance(descuento_porcentual,(int,float))ornot(0<= descuento_porcentual <=100):print("Advertencia: El descuento debe ser un número entre 0 y 100. Se aplicará 0%.") descuento_porcentual =0# Aplicamos la fórmula del descuento descuento_monetario = total_bruto *(descuento_porcentual /100) total_neto = total_bruto - descuento_monetario
returnround(total_neto,2)# Ejemplo 1: Sin descuentoprint(f"Total sin descuento: {calcular_total(100,200,300)}")# 600.0# Ejemplo 2: Con descuento del 10%print(f"Total con 10% de descuento: {calcular_total(100,200,300, descuento=10)}")# 540.0# Ejemplo 3: Diferentes preciosprint(f"Total productos varios: {calcular_total(15.99,42.50,10.00, descuento=15)}")# 58.22
def calcular_total(*args,**kwargs): total =0 detalle =[]for i, precio inenumerate(args, start=1): producto = f"producto_{i}" descuento = kwargs.get(producto,0) precio_final = precio -(precio * descuento) detalle.append((producto, precio, descuento, precio_final)) total += precio_final
return total, detalle
# ✅ Llamada correcta
total, detalle =calcular_total( # ---args(precios)---1000,2000,1500,500,9000,1600,4200,5300,7900,1650, # ---kwargs(descuentos)--- producto_2=0.10, # 10% de descuento en el segundo producto
producto_5=0.25, # 25% de descuento en el quinto producto
producto_10=0.50 # 50% de descuento en el décimo producto
)print("Detalle de la compra:")for prod, precio, desc, final indetalle:print(f"{prod}: ${precio} - Descuento {desc*100:.0f}% -> Final: ${final}")print(f"\nTotal a pagar: ${total}")
def shop_1(*args,**kwargs): suma =sum(args)print(f"El sub total de su compra es {suma}")print(f"El descuento que tiene es {kwargs["descuento"]}")print(f"El total a pagar será {suma * (1 - 0.01 * kwargs["descuento"])}")print(shop_1(200,100,50,650,descuento =10))
classProductos: def __init__(self,*args,**kwargs): self.precio= args self.descuento= kwargs def aplicar_descuento(self): temp_descuento = self.descuento.get("descuento",0)if temp_descuento >0:print(f"Se aplica un descuento de {temp_descuento}%")else:print("No se aplico un descuento")p1 =Productos(100,200,300, descuento=10)p1.aplicar_descuento()
#Crear una funcion que reciba una cantidad variable de productos y sus precios,# calcule el total y aplique un descuento opcional si se proporciona como un argumento con nombre
#1.Usar args para recibir una lista de precios.#2.Usar kwargs para aceptar un dscuento opcional y aplicarlo al total
def calcular_total(*precios,**opciones): total =sum(precios) descuento = opciones.get('descuento',0) total_con_descuento = total *(1- descuento /100)return total_con_descuento
print(calcular_total(10,20,30)) # Sin descuento:60.0print(calcular_total(50,25, descuento=10)) # Con10% descuento:67.5
¿Qué tipo de valores se agrupan dentro de *args cuando se utiliza en una función?
En args se agrupan valores no posicionales, que se guardan en una tupla y no es mutable.