python - funciones - ¿Qué significan*args y** kwargs?
kwargs python 3 (5)
Esta pregunta ya tiene una respuesta aquí:
¿Qué significan exactamente *args
y **kwargs
?
Según la documentación de Python, por lo que parece, pasa en una tupla de argumentos.
def foo(hello, *args):
print hello
for each in args:
print each
if __name__ == ''__main__'':
foo("LOVE", ["lol", "lololol"])
Esto imprime:
LOVE
[''lol'', ''lololol'']
¿Cómo los usas efectivamente?
Además, los usamos para gestionar la herencia.
class Super( object ):
def __init__( self, this, that ):
self.this = this
self.that = that
class Sub( Super ):
def __init__( self, myStuff, *args, **kw ):
super( Sub, self ).__init__( *args, **kw )
self.myStuff= myStuff
x= Super( 2.7, 3.1 )
y= Sub( "green", 7, 6 )
De esta manera, Sub no sabe realmente (o le importa) qué es la inicialización de la superclase. Si se da cuenta de que necesita cambiar la superclase, puede arreglar las cosas sin tener que sudar los detalles en cada subclase.
Observe lo bueno en el comentario de S.Lott : también puede llamar a las funciones con *mylist
y **mydict
para desempaquetar los argumentos posicionales y de palabras clave:
def foo(a, b, c, d):
print a, b, c, d
l = [0, 1]
d = {"d":3, "c":2}
foo(*l, **d)
Se imprimirá: 0 1 2 3
Otro buen uso para *args
y **kwargs
: puede definir funciones genéricas de "captura de todos", lo cual es ideal para decoradores a los que devuelve una envoltura de este tipo en lugar de la función original.
Un ejemplo con un decorador de almacenamiento en caché trivial:
import pickle, functools
def cache(f):
_cache = {}
def wrapper(*args, **kwargs):
key = pickle.dumps((args, kwargs))
if key not in _cache:
_cache[key] = f(*args, **kwargs) # call the wrapped function, save in cache
return _cache[key] # read value from cache
functools.update_wrapper(wrapper, f) # update wrapper''s metadata
return wrapper
import time
@cache
def foo(n):
time.sleep(2)
return n*2
foo(10) # first call with parameter 10, sleeps
foo(10) # returns immediately
Poner *args
y / o **kwargs
como los últimos elementos en la lista de argumentos de su definición de función permite que la función acepte un número arbitrario de argumentos y / o argumentos de palabras clave.
Por ejemplo, si desea escribir una función que devuelva la suma de todos sus argumentos, no importa cuántos suministre, podría escribirla así:
def my_sum(*args):
return sum(args)
Es probable que se use más comúnmente en la programación orientada a objetos, cuando está anulando una función y desea llamar a la función original con cualquier argumento que el usuario transmita.
No tienes que llamarlos args
y kwargs
, eso es solo una convención. Son los *
y **
que hacen la magia.
La documentación oficial de Python tiene una mirada más profunda .
Solo para aclarar cómo descomprimir los argumentos y cuidar los argumentos faltantes, etc.
def func(**keyword_args):
#-->keyword_args is a dictionary
print ''func:''
print keyword_args
if keyword_args.has_key(''b''): print keyword_args[''b'']
if keyword_args.has_key(''c''): print keyword_args[''c'']
def func2(*positional_args):
#-->positional_args is a tuple
print ''func2:''
print positional_args
if len(positional_args) > 1:
print positional_args[1]
def func3(*positional_args, **keyword_args):
#It is an error to switch the order ie. def func3(**keyword_args, *positional_args):
print ''func3:''
print positional_args
print keyword_args
func(a=''apple'',b=''banana'')
func(c=''candle'')
func2(''apple'',''banana'')#It is an error to do func2(a=''apple'',b=''banana'')
func3(''apple'',''banana'',a=''apple'',b=''banana'')
func3(''apple'',b=''banana'')#It is an error to do func3(b=''banana'',''apple'')