2012-03-26 11 views
82

que no entiendo el siguiente ejemplo, digamos que tengo estas funciones:pase ** kwargs argumento a otra función con kwargs **

# python likes 
def save(filename, data, **kwargs): 
    fo = openX(filename, "w", **kwargs) # <- #1 
    fo.write(data) 
    fo.close() 
# python doesnt like 
def save2(filename, data, **kwargs): 
    fo = openX(filename, "w", kwargs) # <- #2 
    fo.write(data) 
    fo.close() 

def openX(filename, mode, **kwargs): 
    #doing something fancy and returning a file object 

Por qué el # 1 la solución adecuada y # 2 el incorrecto ? **kwargs es básicamente un dict, así que si quiero pasar el argumento a openX, creo que la forma correcta sería sin ** y acaba de dar el dict. Pero obviamente Python no le gusta el segundo y me dice que di 3 en lugar de 2 argumentos. ¿Cuál es la razón detrás de esto?

+3

Me pregunto por qué lo llamas '** args' en el código. Este es posiblemente el peor nombre posible ya que las personas lo confundirán con '* args' –

+1

. Bueno, yo nunca uso * args, así que uso ** args ^^, pero bueno, puedo modificarlo. –

Respuesta

84

En el segundo ejemplo se proporcionan 3 argumentos: nombre de archivo, de modo y un diccionario (kwargs). Pero Python espera: 2 argumentos formales más argumentos de palabra clave.

Al anteponer el diccionario por '**' se descomprime el diccionario kwargs a las palabras clave arguments.

Un diccionario (tipo dict) es una variable única que contiene pares clave-valor.

"Argumentos de palabra clave" son parámetros-método de clave-valor.

Cualquier diccionario puede descomprimido en argumentos de palabras clave prefijándolo con ** durante la llamada a la función.

+3

ahora lo entiendo. Pensé que las palabras claves y el dict eran la misma cosa. –

+7

"Cualquier diccionario se puede expandir a palabras clave prefijándolo con ** durante la llamada de función." <- Eso es genial –

+1

Ver también: documentos de Python en [parámetros de palabras clave] (https://docs.python.org/2/tutorial/controlflow.html#keyword-arguments) y [listas de argumentos para desempaquetar] (https: // docs .python.org/2/tutorial/controlflow.html # desempaquetar-argumentos-listas) – dinosaur

1

Porque un diccionario tiene un valor único. Debe usar la expansión de palabras clave si desea pasarlo como un grupo de argumentos de palabra clave.

+0

lo siento, pero ¿qué es una "expansión de palabras clave"? ¿quieres decir que debería usar dict_var en lugar de ** args y simplemente usar def func (argumento, dict_var = 0) ... func (1, {1: "a", 2: "b"}) –

1

Para # 2 args será solo un parámetro formal con valor dict, pero no un parámetro de tipo palabra clave.

Si desea pasar un parámetro de tipo de palabra clave en un argumento de palabra clave Es necesario ** específico antes de su diccionario, lo que significa args **

mira esto para obtener más detalles sobre el uso ** kw

http://www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/

+0

Entonces, hay un gran diferencia entre ** kwargs y dict? –

+0

@xMRW actualización respuesta espero ayuda –

+0

gracias, siempre me gusta leer más sobre temas que no entiendo. –

8

La sintaxis ** le dice a Python que recoja los argumentos de palabra clave en un diccionario. El save2 lo está pasando como un argumento que no es una palabra clave (un objeto de diccionario). El openX no ve ningún argumento de palabras clave, por lo que **args no se usa. En su lugar, obtiene un tercer argumento que no es de palabras clave (el diccionario). Para arreglar eso, cambie la definición de la función openX.

def openX(filename, mode, kwargs): 
    pass 
+0

Gracias, pero también quiero usar openX sin guardar, así que me tengo que quedar con las palabras clave. Pensé que pasar palabras clave era básicamente lo mismo que pasar un dict pero hasta ahora no sabía :) –

+0

@xMRW \t No pueden ser lo mismo, ya que puede pasar un diccionario como parámetro a cualquier función como bien. Tu # 1 es el correcto entonces. – Keith

Cuestiones relacionadas