Uso de * args y ** kwargs

Así que tengo dificultades con el concepto de *args y **kwargs .

Hasta ahora he aprendido que:

  • *args = lista de argumentos – como argumentos posicionales
  • **kwargs = diccionario – cuyas claves se convierten en argumentos de palabras clave separadas y los valores se convierten en valores de estos argumentos.

No entiendo para qué tarea de progtwigción sería útil.

Tal vez:

Creo que para ingresar listas y diccionarios como argumentos de una función Y al mismo tiempo que un comodín, ¿puedo pasar CUALQUIER argumento?

¿Hay un ejemplo simple para explicar cómo se usan *args y **kwargs ?

También el tutorial que encontré usaba solo el “*” y un nombre de variable.

¿Son *args y **kwargs solo marcadores de posición o usas exactamente *args y **kwargs en el código?

La syntax es el * y ** . Los nombres *args y **kwargs son solo por convención, pero no hay un requisito estricto para usarlos.

*args cuando no esté seguro de cuántos argumentos podrían pasarse a su función, es decir, le permite pasar un número arbitrario de argumentos a su función. Por ejemplo:

 >>> def print_everything(*args): for count, thing in enumerate(args): ... print( '{0}. {1}'.format(count, thing)) ... >>> print_everything('apple', 'banana', 'cabbage') 0. apple 1. banana 2. cabbage 

De manera similar, **kwargs permite manejar argumentos con nombre que no ha definido de antemano:

 >>> def table_things(**kwargs): ... for name, value in kwargs.items(): ... print( '{0} = {1}'.format(name, value)) ... >>> table_things(apple = 'fruit', cabbage = 'vegetable') cabbage = vegetable apple = fruit 

Puede utilizar estos junto con argumentos con nombre también. Los argumentos explícitos obtienen valores primero y luego todo lo demás se pasa a *args y **kwargs . Los argumentos nombrados son los primeros en la lista. Por ejemplo:

 def table_things(titlestring, **kwargs) 

También puede usar ambas en la misma definición de función, pero *args debe aparecer antes de **kwargs .

También puede usar la syntax * y ** al llamar a una función. Por ejemplo:

 >>> def print_three_things(a, b, c): ... print( 'a = {0}, b = {1}, c = {2}'.format(a,b,c)) ... >>> mylist = ['aardvark', 'baboon', 'cat'] >>> print_three_things(*mylist) a = aardvark, b = baboon, c = cat 

Como puede ver en este caso, toma la lista (o tupla) de elementos y la desempaqueta. Por esto los relaciona con los argumentos en la función. Por supuesto, podría tener un * tanto en la definición de función como en la llamada de función.

Un lugar donde el uso de *args y **kwargs es bastante útil es para subclasificar.

 class Foo(object): def __init__(self, value1, value2): # do something with the values print value1, value2 class MyFoo(Foo): def __init__(self, *args, **kwargs): # do something else, don't care about the args print 'myfoo' super(MyFoo, self).__init__(*args, **kwargs) 

De esta manera, puede ampliar el comportamiento de la clase Foo, sin tener que saber demasiado sobre Foo. Esto puede ser muy conveniente si está progtwigndo para una API que podría cambiar. MyFoo solo pasa todos los argumentos a la clase Foo.

Aquí hay un ejemplo que usa 3 tipos diferentes de parámetros.

 def func(required_arg, *args, **kwargs): # required_arg is a positional-only parameter. print required_arg # args is a tuple of positional arguments, # because the parameter name has * prepended. if args: # If args is not empty. print args # kwargs is a dictionary of keyword arguments, # because the parameter name has ** prepended. if kwargs: # If kwargs is not empty. print kwargs >>> func() Traceback (most recent call last): File "", line 1, in  TypeError: func() takes at least 1 argument (0 given) >>> func("required argument") required argument >>> func("required argument", 1, 2, '3') required argument (1, 2, '3') >>> func("required argument", 1, 2, '3', keyword1=4, keyword2="foo") required argument (1, 2, '3') {'keyword2': 'foo', 'keyword1': 4} 

Aquí está uno de mis lugares favoritos para usar la syntax ** como en el ejemplo final de Dave Webb:

 mynum = 1000 mystr = 'Hello World!' print "{mystr} New-style formatting is {mynum}x more fun!".format(**locals()) 

No estoy seguro de que sea terriblemente rápido en comparación con solo usar los nombres en sí, ¡pero es mucho más fácil de escribir!

Un caso en el que * args y ** kwargs son útiles es cuando se escriben funciones de envoltorio (como los decoradores) que necesitan poder aceptar argumentos arbitrarios para pasar a la función que se está envolviendo. Por ejemplo, un decorador simple que imprime los argumentos y el valor de retorno de la función que se está envolviendo:

 def mydecorator( f ): @functools.wraps( f ) def wrapper( *args, **kwargs ): print "Calling f", args, kwargs v = f( *args, **kwargs ) print "f returned", v return v return wrapper 

* args y ** kwargs son características especiales de magia de Python. Piense en una función que podría tener un número desconocido de argumentos. Por ejemplo, por cualquier motivo, desea tener una función que sume un número desconocido de números (y no desea utilizar la función de sum integrada). Así que escribes esta función:

 def sumFunction(*args): result = 0 for x in args: result += x return result 

y úsalo como: sumFunction (3,4,6,3,6,8,9).

** Kwargs tiene una función diferente. Con ** kwargs puede dar argumentos de palabra clave arbitrarios a una función y puede acceder a ellos como un diccionario.

 def someFunction(**kwargs): if 'text' in kwargs: print kwargs['text'] 

Al llamar a someFunction (text = “foo”) se imprimirá foo.

Solo imagine que tiene una función pero no desea restringir la cantidad de parámetros que toma. Ejemplo:

 >>> import operator >>> def multiply(*args): ... return reduce(operator.mul, args) 

Entonces usas esta función como:

 >>> multiply(1,2,3) 6 or >>> numbers = [1,2,3] >>> multiply(*numbers) 6 

Los nombres *args y **kwargs o **kw son puramente por convención. Nos facilita la lectura del código de cada uno.

Un lugar en el que está a mano es cuando se usa el módulo de estructura.

struct.unpack() devuelve una tupla mientras que struct.pack() usa un número variable de argumentos. Cuando se manipulan datos, es conveniente poder pasar una tupla a struck.pack() por ejemplo.

 tuple_of_data = struct.unpack(format_str, data) ... manipulate the data new_data = struct.pack(format_str, *tuple_of_data) 

sin esta habilidad estarías obligado a escribir

 new_data = struct.pack(format_str, tuple_of_data[0], tuple_of_data[1], tuple_of_data[2],...) 

lo que también significa que si cambia format_str y cambia el tamaño de la tupla, tendré que volver y editar esa línea realmente larga

Tenga en cuenta que * args / ** kwargs es parte de la syntax de llamada de funciones, y no es realmente un operador. Esto tiene un efecto secundario particular con el que me encontré, que es que no se puede usar la expansión * args con la statement de impresión, ya que la impresión no es una función.

Esto parece razonable:

 def myprint(*args): print *args 

Desafortunadamente no se comstack (error de syntax).

Esto comstack:

 def myprint(*args): print args 

Pero imprime los argumentos como una tupla, que no es lo que queremos.

Esta es la solución que decidí:

 def myprint(*args): for arg in args: print arg, print 

Estos parámetros se utilizan normalmente para las funciones de proxy, por lo que el proxy puede pasar cualquier parámetro de entrada a la función de destino.

 def foo(bar=2, baz=5): print bar, baz def proxy(x, *args, **kwargs): # reqire parameter x and accept any number of additional arguments print x foo(*args, **kwargs) # applies the "non-x" parameter to foo proxy(23, 5, baz='foo') # calls foo with bar=5 and baz=foo proxy(6)# calls foo with its default arguments proxy(7, bar='asdas') # calls foo with bar='asdas' and leave baz default argument 

Pero como estos parámetros ocultan los nombres de los parámetros reales, es mejor evitarlos.

Puede echar un vistazo a los documentos de python (docs.python.org en las Preguntas frecuentes), pero más específicamente para una buena explicación, la misteriosa miss args y mister kwargs (cortesía de archive.org) (el enlace original y muerto está aquí ).

En pocas palabras, ambos se usan cuando se usan parámetros opcionales para una función o método. Como dice Dave, * args se usa cuando no sabes cuántos argumentos se pueden pasar, y ** kwargs cuando quieres manejar los parámetros especificados por nombre y valor como en:

 myfunction(myarg=1)