**kwargs siempre me sonó a WARRRRRRRRRRRRRRRRRRRRRRRRRGGGGGGGHH o algo así como lo que usaría un orco para salir al campo de guerra. De hecho, me hizo acordar al mejor recurso para construir unidades que puede tener un juego de estrategia. Y cuando hablo de juego de estrategia hablo de Warhammer 40000 (Dawn of War y sus expansiónes). Los orcos tienen el Waagh!, que viene a ser una mezcla de guerra santa, migración y violencia galáctica, como un movimiento sindical, pero con menos lucha de clases.
La cuestión es que me fuí por las ramas. Bueno.
Supongamos que, en Python, queremos hacer un programa que sume una cantidad indeterminada de números. Claro, podemos hacer un programa rápido tipo “mientras usario no escriba BASTA hacer: suma = suma + valor_ingresado”, pero por suerte, tenemos magia pythonesca:
Veamos:
def suma(*args):
return sum(args)
Y ya está!
>>> suma(1100)
1100
>>> suma(21,2,2,3,4,5,6,7,6,6,6,6,6)
80
>>> suma (1,2,3,4,5,6,7,8,8,9,0,100231,1.2)
100285.2
>>> a = 40
>>> suma (a,a*2,a**a)
12089258196146291747061760000000000000000000000000000000000000120L
Bueno, en ese me zarpé. Pero creo que se entiende, no? No importa cuantos parámetros pasemos (siempre que no caigamos en un loop infinito), Python agarra los argumentos que le pasamos y los suma (con sum)
Otro ejemplo
>>> def saludo(*args):
… for nombre in args:
… print “hola, %s” % nombre
…
>>> saludo(u”Nicolás”, “Sergio”)
hola, Nicolás
hola, Sergio
Bellísimo! hora de ahorrar un poco de código. Ahora bien, *args creo que está explicado (y creedme, en la hay gente que explica mucho mejor que yo), ¿Cómo es la onda con **kwargs?.
Bueno, es casi lo mismo que *args, pero se diferencian en algo muy interesante. *args solo sirve para argumentos “sueltos” (sin palabras clave o variables), como vimosen los ejemplos. O sea, tomando “saludo()”, no podría haber hecho “saludo(nombre=”tomate”)”
>>> saludo(nombre=”Tomate”)
Traceback (most recent call last):
File “<stdin>”, line 1, in <module>
TypeError: saludo() got an unexpected keyword argument ‘nombre’
Porque justamente, le estoy pasando un argumento CON NOMBRE. Acá entra en acción **kwargs (Keyword Arguments, o KWARRRRRRRRRRRRRRRGH!)
>>> def saludo(**kwargs):
… for nombre in kwargs:
… print u”hola %s, estás en %s” % (kwargs[nombre], nombre)
…
>>> saludo (n1 = “nico”, n2=”blog”, n3=”melissa”)
hola nico, estás en n1
hola blog, estás en n2
hola melissa, estás en n3
Espectacular, ¿no?
Otra joyita, de paso, es saber que kwargs y args no tienen importancia. LO VITAL son los * y los **, que determinan si vas a pasar argumentos con clave o no. Igual se recomienda que usemos args y kwargs para tener un código más legible
Un ejemplo al voleo:
>>> def otro_nombre(**pato):
… for animal in pato:
… print u”dentro de %s está el %s” % (animal, pato[animal])
…
>>> otro_nombre(caramelo=”santo”)
dentro de caramelo está el santo
claro, el santo!
Una buena lectura sobre el tema (con ejemplos más bonitos) acá