Explicación de args y kwargs en Python. Función promedio

Entendiendo *args y **kwargs en Python

En este post explicaré para qué sirven y cómo se usan los *args y **kwargs en las llamadas a las funciones de Python 3.

Explicación de args y kwargs en Python. Función promedio
Explicación de args y kwargs en Python. Función promedio

Esto permite llamar a funciones que reciben un número indefinido de argumentos; y también cuando necesitamos múltiples argumentos opcionales. Vamos a ver algunos ejemplos.

Las funciones y los argumentos

Recordemos que las funciones son algo así:

def funcion(un_argumento)

Y que pueden tener más de un argumento:

def sumar(numero1, numero2)

O no tener ninguno:

def funcion()

Dentro de las funciones, se pueden usar a los argumentos para lo que sea necesario.

Explicando *args en Python

Este nombre no es obligatorio (la sintaxis sí), podría ser, por ejemplo, *argumentos o cualquier otra cosa siempre y cuando se ponga el asterisco antes del nombre.

Para ejemplificar esto, pongamos el ejemplo de una función que calcule el promedio de algunos valores. ¿Cuántos valores? no sabemos, por eso es que recibimos infinitos argumentos gracias a *args.

Dejaré que el código hable por mí:

La función es definida, pero con un argumento un poco especial: *numeros. Eso le indica a Python que sea una función que puede recibir desde 0 hasta infinitos argumentos. Así, se puede invocar a la misma con cualquier número de argumentos.

En este caso fue con argumentos enteros, pero podrían ser cadenas, URL’s de imágenes para descargar, etcétera. Lo importante o interesante es que podemos recorrer los argumentos

No es que esto sea algo nuevo, las funciones con un número indefinido

Más sobre *args en Python

Sólo para mencionar que podemos tener una función que reciba tanto un argumento posicional y los demás infinitos.

Por ejemplo, una que calcule promedios y reciba el nombre de una persona (sólo para ejemplificar) quedaría así:

def promedio(nombre, *argumentos)

Por cierto, no se puede tener dos veces a *args. Lo siguiente es erróneo:

def funcion(*argumentos, *otros_argumentos)

Y no se pueden tener a argumentos posicionales después de los argumentos infinitos. Lo siguiente no es correcto:

def function(*argumentos, un_argumento)

Uso de **kwargs en Python

Igualmente no es necesario poner kwargs, sino los dos asteriscos.

Por ejemplo, podría usarse el nombre de **argumentos_con_nombre ya que más o menos eso quieren decir (no literalmente, porque en inglés significa keyword arguments)

Estos kwargs en Python son usados para dos cosas que veremos a continuación.

Cuando una función recibe muchos argumentos

Por ejemplo, una función que conecte a MongoDB desde Python. Supongamos que queda así:

def conectar(host, puerto, usuario, palabra_secreta, nombre_base_de_datos)

Sé que no es tan larga, pero imaginemos que más adelante le agregamos más parámetros. Quedaría muy larga, mucho más. Así que mejor la definimos así:

def conectar(**opciones)

Veamos el código:

En él indicamos que vamos a recibir una lista de argumentos con nombre con los dos asteriscos **, y en la función accedemos a ellos como cuando accedemos a un diccionario.

Ahora vemos la llamada, la cual puede ser primero definiendo un diccionario y pasándolo con **:

El código de arriba confunde un poco, porque tenemos que usar ** al llamar a la función, aparte de cuando la definimos. La otra opción que es más expresiva y legible es la siguiente:

A mi parecer es más legible, y no hay necesidad de definir un diccionario. Además, el comportamiento dentro de la función es el mismo, al final es un diccionario que tiene claves y valores.

En caso de tener múltiples argumentos, pero que algunos sean opcionales

Ahora veamos otro uso clave de kwargs en Python. Esto va combinado con lo que vimos acerca de switch en Pyhton.

¿Qué pasa si algunos argumentos tienen valores por defecto o son opcionales? muy fácil, usamos al método get  de los diccionarios y proveemos un valor por defecto, algo así:

De esta manera, aunque no se proporcionen todos los datos (por ejemplo, pasar únicamente el usuario y la contraseña), no habrá errores:

conectar(usuario="parzibyte", palabra_secreta="hunter2")

En ese caso se tomarán los demás valores por defecto. Cabe mencionar que no tenemos que pasar a los argumentos en orden, lo de arriba igualmente podría ser así:

conectar(palabra_secreta="hunter2", usuario="parzibyte")

Esa es una de las ventajas de **kwargs en Python.

Diferencia entre **kwargs y *args en Python

Los **kwargs tienen nombre, aunque estén desordenados, pero tienen un nombre. En cambio, *args es una lista plana, no se sabe qué valor se encuentra en determinada posición.

Infiero que los keyword arguments son usados para definir valores por defecto en funciones que toman muchos de los mismos.

Usar argumentos, **kwargs y *args en Python en la misma función

Justo ahora no se me ocurre un uso, pero claro que se pueden usar en conjunto. Sólo recuerda estas reglas:

  1. Primero van los argumentos posicionales
  2. Luego, opcionalmente, va *args
  3. Finalmente, va **kwargs

Veamos este ejemplo:

En ese caso el argumento posicional es nombre, pero podría haber más. Después definimos los argumentos indefinidos, y finalmente pasamos los **kwargs. Recuerda que en lugar de estos últimos, podríamos definir un diccionario y pasarlo con **diccionario.

¿Quieres probar el código? puedes descargarlo y ejecutarlo, pero primero instala el intérprete de Python. O puedes ejecutarlo aquí, sin salir del post:

Espero que haya quedado claro. Si tienes dudas, ahí están los comentarios.

Encantado de ayudarte


Estoy disponible para trabajar en tu proyecto, modificar el programa del post o realizar tu tarea pendiente, no dudes en ponerte en contacto conmigo.

No te pierdas ninguno de mis posts

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

2 comentarios en “Entendiendo *args y **kwargs en Python”

  1. Pingback: Conversión de texto a voz (TTS) con Python y gTTS - Parzibyte's blog

  2. Pingback: Comprobar si diccionario tiene determinada clave en Python - Parzibyte's blog

Dejar un comentario