No entiendo el siguiente ejemplo, digamos que tengo estas funciones:
# 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é es # 1 la solución correcta y # 2 la incorrecta? **kwargs
es básicamente un dict, así que si quiero pasar el argumento a openX creo que la forma correcta sería sin **
y solo dict el dict. Pero a python obviamente no le gusta el segundo y me dice que di 3 argumentos en lugar de 2. Entonces, ¿cuál es la razón detrás de esto?
**args
en el código. Esto es posiblemente el peor nombre posible, ya que la gente se confunda con*args
Respuestas:
En el segundo ejemplo, proporciona 3 argumentos: nombre de archivo, modo y un diccionario (
kwargs
). Pero Python espera: 2 argumentos formales más argumentos de palabras clave.Al prefijar el diccionario con '**', descomprime el diccionario
kwargs
en argumentos de palabras clave.Un diccionario (tipo
dict
) es una variable única que contiene pares clave-valor.Los "argumentos de palabras clave" son parámetros-método clave-valor.
Cualquier diccionario puede descomprimirse en argumentos de palabras clave con el prefijo
**
durante la llamada a la función.fuente
La
**
sintaxis le dice a Python que recopile argumentos de palabras clave en un diccionario. Lasave2
está pasando como un argumento sin palabras clave (un objeto de diccionario). NoopenX
está viendo ningún argumento de palabra clave, por lo**args
que no se utiliza. En su lugar, está obteniendo un tercer argumento sin palabras clave (el diccionario). Para arreglar eso, cambie la definición de laopenX
función.fuente
Ampliando la respuesta de @gecco, el siguiente es un ejemplo que le mostrará la diferencia:
Aquí puede ver cómo funciona desempacar un diccionario y por qué falla el envío de un diccionario real
fuente
Porque un diccionario es un valor único. Debe usar la expansión de palabras clave si desea pasarla como un grupo de argumentos de palabras clave.
fuente
Para # 2, los argumentos serán solo un parámetro formal con valor dict, pero no un parámetro de tipo de palabra clave.
Si desea pasar un parámetro de tipo de palabra clave a un argumento de palabra clave, debe especificar ** antes de su diccionario, lo que significa ** argumentos
mira esto para más detalles sobre el uso de ** kw
http://www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/
fuente