2008-11-13 20 views
231

¿Qué significa exactamente *args y **kwargs?¿Qué significa * args y ** kwargs?

De acuerdo con la documentación de Python, de lo que parece, se 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 muestra:

LOVE 
['lol', 'lololol'] 

¿Cómo se utiliza de manera efectiva?

+13

Sólo un mal juego de palabras en Horas y Kilo -Watt Hours. – Mostlyharmless

+6

Este artículo puede ser muy útil para comprender en profundidad el tema: http://agiliq.com/blog/2012/06/understanding-args-and-kwargs/ –

Respuesta

225

Poner *args y/o **kwargs como los últimos elementos en la lista de argumentos de definición de su función permite que esa función acepte un número arbitrario de argumentos y/o argumentos de palabra clave.

Por ejemplo, si desea escribir una función que devuelve la suma de todos sus argumentos, no importa cuántos usted suministra, se podría escribir así:

def my_sum(*args): 
    return sum(args) 

Es probable que más comúnmente utilizado en programación orientada a objetos, cuando se está anulando una función, y quieren llamar a la función original con cualquier argumento que el usuario pasa en.

en realidad no tiene que llamarlos args y kwargs, eso es sólo una convención. Es el * y el ** que hacen la magia.

La documentación oficial de Python tiene a more in-depth look.

+5

No hay problema, eres bienvenido. Me confundió por un tiempo también. Si te estás metiendo en Python en serio, te recomendaría sinceramente 'Programming Python' de Mark Lutz. –

+39

Quizás enlace al tutorial que explica esto en profundidad, y debe ser leído por todos: http://docs.python.org/tutorial/controlflow.html#more-on-defining-functions –

+1

@AliAfshar: Su enlace fue todo Necesitaba, debería haber sido la respuesta por sí mismo. ¡Gracias! – scorpiodawg

82

Además, los usamos para administrar 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 (ni le importa) 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.

+6

Esta es una de las respuestas más útiles que he encontrado sobre cómo usar 'super'. Esta respuesta tiene más de 5 años, pero supongo que esta sigue siendo una excelente forma de usar 'super' en Python 2.X, ¿correcto? –

+0

Sí, sigue siendo la manera de hacerlo. –

+0

Gracias, pero sería genial si pudiera proporcionar un ejemplo real, por qué y cuándo usarlo. En el ejemplo anterior, ¿qué sucede si hago eso? – TaraGurung

63

Aviso lo bueno en S.Lott's comment - también se puede llamar a funciones con *mylist y **mydict para desempaquetar 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) 

imprimirá: 0 1 2 3

+0

Usted puede hacer también '* mydict' (no' ** mylist'), pero el resultado será ligeramente diferente (e inesperado para algunos). – Tadeck

+1

simple, conciso, y un ejemplo fácil de seguir para ilustrar el punto. Mi tipo de respuesta favorita! – NickO

+0

@Tadeck Puede hacer '* x' para cualquier iterable y' ** y' para cualquier tipo de mapeo. Como un dict es un iterable y un mapeo, puedes hacer cualquiera de los dos. Ver también http://stackoverflow.com/questions/8601268/python-class-hathat-acts-as-mapping-for-unpacking – augurar

24

Otro buen uso para *args y **kwargs: puede definir funciones genéricas de "capturar todo", lo cual es ideal para los decoradores en los que devuelve dicho envoltorio en lugar de la función original.

Un ejemplo trivial con un decorador de almacenamiento en caché:

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 
15

sólo para aclarar el modo de desempaquetar los argumentos, y cuidar de los argumentos que faltan 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') 
Cuestiones relacionadas