passare l'argomento ** kwargs a un'altra funzione con ** kwargs


152

Non capisco il seguente esempio, diciamo che ho queste funzioni:

# 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

Perché # 1 è la soluzione giusta e # 2 quella sbagliata? **kwargsè fondamentalmente un dict, quindi se voglio passare l'argomento a openX penso che il modo corretto sarebbe senza **e solo dare il dict. Ma a Python ovviamente non piace il secondo e mi dice che ho dato 3 invece di 2 argomenti. Quindi qual è il motivo dietro questo?

python 

5
Mi chiedo perché lo chiami **argsnel codice. Questo è forse il peggior nome possibile poiché la gente lo confonderà*args
John La Rooy,

1
Beh, non uso mai * args, quindi uso ** args ^^, ma posso modificarlo.

Risposte:


155

Nel secondo esempio vengono forniti 3 argomenti: nome file, modalità e un dizionario ( kwargs). Ma Python si aspetta: 2 argomenti formali più argomenti di parole chiave.

Con il prefisso "**" del dizionario, scompattare il dizionario kwargsin argomenti di parole chiave.

Un dizionario (tipo dict) è una singola variabile contenente coppie chiave-valore.

Gli "argomenti delle parole chiave" sono parametri del metodo valore-chiave.

Qualsiasi dizionario può essere decompresso in argomenti di parole chiave prefissandolo con **durante la chiamata di funzione.


5
ora capisco. Pensavo che parole chiave e dict fossero la stessa cosa.

13
"Qualsiasi dizionario può essere espanso in parole chiave con il prefisso ** durante la chiamata di funzione." <- è fantastico


8
Un esempio di codice reale renderebbe questa risposta notevolmente più chiara.
OrangeDog,

13

La **sintassi dice a Python di raccogliere argomenti di parole chiave in un dizionario. Lo save2sta passando come argomento non di parole chiave (un oggetto dizionario). Non openXviene visualizzato alcun argomento per le parole chiave, quindi **argsnon viene utilizzato. Sta invece ottenendo un terzo argomento non di parole chiave (il dizionario). Per risolvere il problema, modificare la definizione della openXfunzione.

def openX(filename, mode, kwargs):
    pass

Grazie, ma voglio anche usare openX senza salvare, quindi devo attenermi alle parole chiave. Pensavo che tramandare le parole chiave fosse praticamente lo stesso che tramandare un dict, ma fino ad ora non lo sapevo :)

@xMRW Non possono essere la stessa cosa poiché puoi passare un dizionario come parametro anche a qualsiasi funzione. Il tuo numero 1 è quello giusto allora.
Keith,

8

Espandendo la risposta di @gecco, il seguente è un esempio che ti mostrerà la differenza:

def foo(**kwargs):
    for entry in kwargs.items():
        print("Key: {}, value: {}".format(entry[0], entry[1]))

# call using normal keys:
foo(a=1, b=2, c=3)
# call using an unpacked dictionary:
foo(**{"a": 1, "b":2, "c":3})

# call using a dictionary fails because the function will think you are
# giving it a positional argument
foo({"a": 1, "b": 2, "c": 3})
# this yields the same error as any other positional argument
foo(3)
foo("string")

Qui puoi vedere come funziona il disimballaggio di un dizionario e perché non è possibile inviare un dizionario reale


1

Perché un dizionario è un singolo valore. È necessario utilizzare l'espansione delle parole chiave se si desidera passarlo come gruppo di argomenti delle parole chiave.


scusa ma cos'è una "espansione di parole chiave"? vuoi dire che dovrei usare dict_var invece di ** args e solo usando def func (argomento, dict_var = 0) ... func (1, {1: "a", 2: "b"})

1

Per # 2 args sarà solo un parametro formale con valore dict, ma non un parametro del tipo di parola chiave.

Se si desidera passare un parametro del tipo di parola chiave in un argomento di parola chiave È necessario specificare ** prima del dizionario, il che significa ** args

controlla questo per maggiori dettagli sull'uso di ** kw

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


Quindi c'è una grande differenza tra ** kwargs e dict?

grazie, mi piace sempre leggere di più su argomenti che non capisco.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.