Argumentos Por Posiciones Y Nombre

Fecha de publicaci贸n: 21 Octubre 2021
Tiempo de lectura: 5 min.
Premium: False
N煤mero de visitas: 207


Algo que sin duda me gusta much铆simo de Python es el tema de funciones. Y ya lo he dicho en entregas anteriores, en Python las funciones por s铆 solas se merecen un libro completo. 馃樀

Y no exagero, son demasiados los conceptos que podemos abordar con el tema de funciones, por ejemplo closures, decoradores, scopes, variables locales, globales, lambdas etc...

Sin dejar a un lado que a partir de las funciones podemos pasar de la programaci贸n estructurada a la programaci贸n orientada a objetos, funcional, concurrente etc ...

Es por ello que en esta ocasi贸n me gustar铆a mostrarte un par de features incorporadas al lenguaje que nos permitir谩n crear funciones aun m谩s flexibles, robustas, reutilizables y sobre todo, f谩ciles de mantener.

As铆 que, sin m谩s introducci贸n, comencemos con este post. 馃嵒

Argumentos y par谩metros.

Lo primero que debemos tener en claro, antes de entrar de lleno con los temas principales, es saber la diferencias entre argumentos y par谩metros. Recordando que un argumento no ser谩 m谩s que el valor que vamos a ingresar al momento de llamar a una funci贸n, y los par谩metros ser谩n variables definidas en la funci贸n misma que podr谩n almacenar los argumentos ingresados.

Veamos un ejemplo para recordar.

def suma(a, b, c):
    return a + b + c

En este caso hemos definido la funci贸n suma. Funci贸n que posee 3 par谩metros (a, b y c).

Estos par谩metros no poseen valores por default, esto quiere decir que al hacer el llamado a la funci贸n, ser谩 necesario definir sus valores. Y para ello la forma m谩s sencilla es utilizar argumentos.

Simplemente, al hacer el llamado a la funci贸n, colocamos los argumentos. En este caso 3.

Ejemplos.

# Argumentos por posici贸n
suma(10, 20, 30)
60

En Python la asignaci贸n de argumentos se realiza por posici贸n, esto quiere decir que el primer argumento es asignado al primer par谩metro, el segundo argumento al segundo par谩metro y as铆 sucesivamente. A esta asignaci贸n la conoceremos como positional argument. Y ser谩 la forma m谩s com煤n de llamar a una funci贸n.

Ok, hasta aqu铆 todo bien con los argumentos y los par谩metros. Sin embargo d茅jame decirte que en Python existe otra forma en la cual podemos llamar a una funci贸n, y esta vez lo haremos utilizando el nombre de los par谩metros.

Veamos.

suma(b=10, c=20, a=30)
60

En este caso, como podemos observar, asignamos valores ya no por posici贸n, si no por nombre.

Lo interesante de la asignaci贸n por nombre, es que el orden no importa; solo basta con colocar el nombre del par谩metro (Al cual queremos hacer la asignaci贸n), signo igual (=) y su correspondiente valor. A esta asignaci贸n la conoceremos como keyword argument. 馃暤锔忊嶁檧锔

NOTA: Una muy buena pr谩ctica en Python, es realizar la asignaci贸n por nombre sin espacio. variable=valor.

La asignaci贸n por nombre lo podemos hacer en pr谩cticamente cualquier versi贸n de Python 2.x o 3.x. Lo interesante ocurren en versiones actuales del lenguaje, donde es posible definir que valores podr谩n ser asignados por posici贸n o por nombre.

Keyword only

Listo, los conceptos b谩sicos ya los tenemos, ahora modifiquemos un poco el ejemplo, y trabajemos con solo argumentos por posici贸n.

def suma(a, *, b, c):
    return a + b + c

En este caso hemos a帽adido el asterisco (*) en la secci贸n de par谩metros, pero 驴Qu茅 significa esto? Ver谩s, al hacer esto, le indicamos a Python que todos los par谩metros que se encuentren a la derecha del asterisco 煤nicamente podr谩n tomar su valor por nombre y no por posici贸n.

Si intento ejecutar la funci贸n utilizando 煤nicamente positional arguments obtendremos un error. 馃く

>>> suma(10, 20, 30)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: suma() takes 1 positional argument but 3 were given

El error es bastante claro, la funci贸n solo puede recibir un argumento por posici贸n (que ser铆a para el par谩metro a) pero estamos pasando 3.

Lo quedemos hacer para evitar el error, es simplemente asignar los valores por keyword arguments.

>>> suma(10, b=20, c=30)
60

Ahora s铆, obtendremos el resultado deseado, sin ning煤n error.

Y 驴Qu茅 pasa si intentamos asignar un valor directamente para el par谩metro a?

>>> suma(a=10, b=20, c=30)
60

Bueno, no pasa absolutamente nada.

A los par谩metros que se encuentren a la izquierda del asterisco (*) se les puede asignar su valor ya sea por posici贸n o por nombre. 馃コ

El uso del asterisco (*) nos permite un mayor control sobre la asignaci贸n o modificaci贸n de valores para los par谩metros. Por ejemplo, que pasa si tenemos un par谩metro que tiene un valor por default, pero solo queremos que dicho valor sea modificado cuando el usuario lo haga de forma expl铆cita, es decir, directamente por su nombre.

En esos casos lo mejor que podemos hacer es utilizar el Keyword only. Veamos.

def database_connection(username, password, host, *, port=3306):
    pass

En este caso donde la funci贸n posee 4 par谩metros, pero solo quiero que 3 de ellos puedan ser asignados por posici贸n o nombre, hacemos uso del asterisco. Con lo cual, si el usuario quiere utilizar un puerto diferente al default, debe hacerlo de forma expl铆cita, reduciendo la posibilidad de error.

database_connection('eduardo_gpg', 'password123', 'localhost', port=29017)

Cool.

Positional only

Continuando con el post,algo que me gustar铆a mencionar es que, a partir de la versi贸n 3.8 de Python, es posible la asignaci贸n de valores solo por posici贸n, es decir, lo contrario de lo que acabamos de ver. Y para ello haremos uso del slash (/). 馃悕

def suma(a, b,  /, c):
    return a + b + c

Para este nuevo ejemplo, le indicamos a Python que todos los par谩metro que se encuentren a la izquierda del slash , solo podr谩n tomar su valor por posici贸n y no por nombre.

Si por ejemplo intento ejecutar asignando nombres, obtendr茅 un error.

>>> suma(a=10, b=20, c=30)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: suma() got some positional-only arguments passed as keyword arguments: 'a, b'

De igual forma, el error es bastante claro. No es posible utilizar argumentos por nombre para a y b.

Lo correcto ser铆a hacerlo todo por posici贸n. 馃

>>> suma(10, 20, 30)
60

Lo interesante de todo esto es que, al limitar argumentos solo por posici贸n, en caso deseemos modificar la definici贸n de la funci贸n, por ejemplo que ahora los par谩metros cambien sus nombre (n1, n2 y n3) este cambio no debiera repercutir de ninguna forma a las implementaciones de la funci贸n, ya que la asignaci贸n siempre se hizo por posici贸n y nunca por nombre, por lo tanto ser铆a un cambio completamente transparente para el usuario.

Keyword only & Positional only

Ya para finalizar me gustar铆a mencionar que s铆, es posible hacer uso de los keyword only y positional only en una misma funci贸n. Que si bien, nunca he tenido la necesidad de hacerlo, y siendo sinceros no se me ocurre un escenario para ello. Spi es posible. 馃く

Aqu铆 un peque帽o ejemplo.

def function(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
            -----------    ----------     ----------
                |             |                  |
                |        Positional or keyword   |
                |                                - Keyword only
                -- Positional only

Espero que puedas encontrar un caso pr谩ctico para la implementaci贸n, y s铆 es as铆, no olvides compartirlo en la secci贸n de comentarios. 馃

M谩s Tips y Ejercicios 馃悕

Adquiere una subscripci贸n PyWombat por tan solo $3 USD. al mes.

Conoce los beneficios de ser usuario premium:
Niveles desbloqueados: Ten accesos a todos los niveles de ejercicios. 馃敁
Nuevo l铆mite: Incrementa tu l铆mite de ejercicios por semana. 馃殌
Contenido 煤nico: Recibe semanalmente recursos exclusivos de Python (Videos, Art铆culos y Capitulos del libro PyWombat, comienza como desarrollador Python. 馃悕