* args and * * kwargs? [duplicar]
Esta pregunta ya tiene una respuesta aquí:
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 separados y los valores se convierten en valores de estos argumentos.
No entiendo para qué tarea de programación sería útil esto.
Tal vez:
Creo que para introducir listas y diccionarios como argumentos de una función Y al mismo tiempo como un comodín, por lo que puedo pasar CUALQUIER argumento?
¿Hay un ejemplo sencillo para explicar cómo se usan *args
y **kwargs
?
También el tutorial que encontré utiliza solo el "*" y un nombre de variable.
Son *args
y **kwargs
solo marcadores de posición o utiliza exactamente *args
y **kwargs
en el código?
11 answers
La sintaxis es la *
y **
. Los nombres *args
y **kwargs
son solo por convención, pero no hay ningún requisito difícil de usarlos.
Usaría *args
cuando no esté seguro de cuántos argumentos se pueden pasar 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
Del mismo modo, **kwargs
le 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 los argumentos nombrados 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 ambos en la misma definición de función, pero *args
debe aparecer antes de **kwargs
.
También puede usar la sintaxis *
y **
cuando llame 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 desempaca. Por esto los hace coincidir con los argumentos en la función. Por supuesto, usted podría tener un *
tanto en la definición de la función como en la llamada a la función.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-23 15:15:58
Un lugar donde el uso de *args
y **kwargs
es bastante útil es para la subclase.
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 extender el comportamiento de la clase Foo, sin tener que saber demasiado sobre Foo. Esto puede ser muy conveniente si está programando una API que podría cambiar. MyFoo simplemente pasa todos los argumentos a la clase Foo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-12 13:58:30
Aquí hay un ejemplo que utiliza 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 "<stdin>", line 1, in <module>
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}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-02 00:50:10
Aquí está uno de mis lugares favoritos para usar la sintaxis **
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 si es terriblemente rápido en comparación con solo usar los nombres en sí, pero es mucho más fácil de escribir!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-03 13:03:49
Un caso en el que *args y **kwargs son útiles es cuando se escriben funciones de envoltura (como decoradores) que necesitan ser capaces de aceptar argumentos arbitrarios para pasar a través de la función que se envuelve. Por ejemplo, un decorador simple que imprime los argumentos y el valor de retorno de la función que se envuelve:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-03 08:40:34
* args y * * kwargs son características especiales de Python. Piense en una función que podría tener un número desconocido de argumentos. Por ejemplo, por cualquier razón, desea tener una función que suma un número desconocido de números (y no desea usar la función suma incorporada). Así que escribe 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 diffrent. Con * * kwargs puede dar argumentos arbitrarios de palabras clave a una función y usted puede acceder a ellos como un dictonary.
def someFunction(**kwargs):
if 'text' in kwargs:
print kwargs['text']
Llamando a someFunction(text="foo") imprimirá foo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-03 09:35:18
Imagínese que tiene una función pero no quiere restringir el número de parámetros que toma. Ejemplo:
>>> import operator
>>> def multiply(*args):
... return reduce(operator.mul, args)
Luego usa esta función como:
>>> multiply(1,2,3)
6
or
>>> numbers = [1,2,3]
>>> multiply(*numbers)
6
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-03 08:40:07
Los nombres *args
y **kwargs
o **kw
son puramente por convención. Hace que sea más fácil para nosotros leer el código del otro
Un lugar que es útil es cuando se utiliza el módulo struct
struct.unpack()
devuelve una tupla mientras que struct.pack()
utiliza un número variable de argumentos. Al manipular 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 te verías obligado a escribir
new_data = struct.pack(format_str, tuple_of_data[0], tuple_of_data[1], tuple_of_data[2],...)
Que también significa el si el format_str cambia y el tamaño de la tupla cambia, tendré que volver atrás y editar esa línea realmente larga
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-03 08:39:07
Tenga en cuenta que *args/**kwargs es parte de la sintaxis de llamada a funciones, y no es realmente un operador. Esto tiene un efecto secundario particular con el que me encontré, que es que no puede usar la expansión *args con la instrucción print, ya que print no es una función.
Esto parece razonable:
def myprint(*args):
print *args
Desafortunadamente no compila (error de sintaxis).
Esto compila:
def myprint(*args):
print args
Pero imprime los argumentos como una tupla, que no es lo que queremos.
Esta es la solución que resolví on:
def myprint(*args):
for arg in args:
print arg,
print
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-11 20:29:33
Estos parámetros se usan típicamente para funciones 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 dado que estos parámetros ocultan los nombres de los parámetros reales, es mejor evitarlos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-03 08:41:27
Puedes echar un vistazo a los documentos de python (docs.python.org en las FAQ), pero más específicamente para una buena explicación la misteriosa señorita args y el señor kwargs (cortesía de archive.org) (el enlace original muerto es aquí ).
En pocas palabras, ambos se utilizan cuando se utilizan parámetros opcionales para una función o método. Como dice Dave, * args se usa cuando no sabe cuántos argumentos se pueden pasar, y * * kwargs cuando desea manejar parámetros especificados por nombre y valor como en:
myfunction(myarg=1)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-22 17:38:57