2013-08-12 23 views
10

Ho iniziato a imparare Python, e vorrei chiederti qualcosa che ho considerato un po 'magico in questa lingua.Perché una funzione di chiamata in python contiene una variabile uguale al valore?

Vorrei notare che prima di imparare Python ho lavorato con PHP e lì non l'ho notato.

Cosa sta succedendo - Ho notato che alcuni costruttori o metodi di chiamata in Python sono in questa forma.

object.call(variable1 = value1, variable2 = value2) 

Ad esempio, nel pallone: ​​

app.run(debug=True, threaded=True) 

alcun motivo per questa convenzione? O c'è qualche motivo semantico in uscita dai fondamenti linguistici? Non ho mai visto qualcosa del genere in PHP così spesso come in Python e perché sono davvero sorpreso. Sono davvero curioso di sapere se c'è qualche magia o è solo convenzione leggere il codice più facilmente.

+3

http://docs.python.org/2/tutorial/controlflow.html#keyword-arguments lo spiega abbastanza bene. –

+0

Ho avuto l'esperienza esattamente opposta qualche anno fa, venendo in PHP da Python e confuso quando 'f ($ a = true)' è stato accettato, ma non ha fatto ciò che pensavo facesse. – Ben

risposta

16

Questi sono chiamati keyword arguments e di solito vengono utilizzati per rendere la chiamata più leggibile.

Possono essere utilizzati anche per passare gli argomenti in un ordine diverso dai parametri dichiarati o per saltare alcuni parametri predefiniti ma passare argomenti ad altri o perché la funzione richiede argomenti di parole chiave ... ma la leggibilità è il motivo principale per la loro esistenza

Considerate questo:

app.run(True, False) 

Hai idea di cosa significano questi due argomenti? Anche se puoi indovinare che gli unici due argomenti ragionevoli sono il threading e il debugging dei flag, come puoi indovinare quale viene prima? L'unico modo per farlo è capire che tipo è app e controllare la docstring o la definizione del metodo app.run.

Ma ecco:

app.run(debug=True, threaded=False) 

E 'ovvio che cosa significa.


Vale la pena di leggere le FAQ What is the difference between arguments and parameters?, e le altre sezioni del tutorial vicino quella legata sopra. Quindi è possibile leggere il riferimento su Function definitions per i dettagli completi sui parametri e Calls per i dettagli completi sugli argomenti, e infine la documentazione del modulo inspect sui tipi di parametri.

This blog post tentativi di riassumere tutto in quei riferimenti in modo da non dover leggere la strada attraverso l'intero casino. Gli esempi alla fine dovrebbero anche servire a mostrare perché mescolare argomenti e parametri in generale, argomenti di parole chiave e parametri predefiniti, argomento disimballo e parametri variabili, ecc. Vi porteranno fuori strada.

+0

Vale la pena sottolineare che una funzione può accettare argomenti di parole chiave che non sono definiti esplicitamente tramite l'argomento '** kwargs'. – chepner

+1

@chepner: beh, forse, ma solo se si spiega anche sui parametri delle parole chiave, sul parametro * args e sul passaggio di argomenti variabili e dict parola chiave, il che rende le cose molto più complicate. Vale la pena prima capire le basi e poi leggere il resto del tutorial ... – abarnert

+0

@chepner: Ho provato ad aggiungere collegamenti sufficienti che qualcuno possa effettivamente trovare le informazioni di cui hanno bisogno per arrivare al punto in cui '** kwargs' ha senso e poi impara esattamente come funziona. Ma probabilmente c'è un modo migliore per includere tali informazioni. Eventuali suggerimenti? – abarnert

-2

L'utilità principale della convenzione è che consente di impostare determinati input quando possono esserci alcuni valori predefiniti nel mezzo. È particolarmente utile quando una funzione ha molti parametri, molti dei quali funzionano bene con i loro valori predefiniti, ma alcuni devono essere impostati su altri valori affinché la funzione funzioni come desiderato.

esempio:

def foo(i1, i2=1, i3=3, i4=5): 
    # does something 


foo(1,2,3,4) 

foo(1,2,i4=3) 

foo(1,i2=3) 

foo(0,i3=1,i2=3,i4=5) 
+1

Impostazione dei valori predefiniti quando * definisce * la funzione è un problema un po 'separato dall'uso degli argomenti delle parole chiave quando * chiama * la funzione. – chepner

+0

Io non la penso così. Se si sta bypassando un input tramite parole chiave, gli input bypassati devono/devono avere valori predefiniti, no? – Jiminion

+1

@Jim: No. Leggi le FAQ [Qual è la differenza tra argomenti e parametri] (http://docs.python.org/3/faq/programming.html#what-is-the-difference-between-arguments- e-parametri), e quindi guarda come sono definiti. È possibile passare gli argomenti delle parole chiave per i parametri che non hanno valori predefiniti. Ad esempio, 'def f (a, b): pass', quindi' f (b = 1, a = 2) 'funziona bene. – abarnert

-1

Non v'è alcuna "magia".

Una funzione può prendere:

  • argomenti posizionali (args)
  • argomenti keyworded (kwargs)

è sempre questo ordine.

Prova questa:

def foo(*args, **kwargs): 
    print args 
    print kwargs 

foo(1,2,3,4,a=8,b=12) 

uscita:

(1, 2, 3, 4) 
{'a': 8, 'b': 12} 

memorizza Python gli argomenti posizionali in una tupla, che deve essere immutabile, e quelli keyworded in un dizionario.

+1

Python memorizza solo gli argomenti posizionali il cui indice non corrisponde a un parametro parola-o-posizionale (o un parametro posizionale-solo, ma non hai quelli nelle funzioni definite in Python) nella sequenza var-posizionale, e solo memorizza gli argomenti delle parole chiave il cui nome non corrisponde a un parametro parola chiave o posizionale o solo parola chiave nel mapping della parola chiave var. Dato che l'OP sta chiedendo una funzione che ha due parametri keyword-o-posizionali, questo non è rilevante qui. Nessun tale dict è costruito o passato da nessuna parte. – abarnert

+0

Sono d'accordo, ma non è possibile una risposta provare a mostrare alcune cose aggiuntive non già spiegate da altre risposte? –

+0

Certo, una risposta può essere utile anche se è una digressione ... ma una risposta fuorviante non diventa utile solo perché è una digressione. – abarnert

0

Sono argomenti passati da parole chiave. Non c'è una differenza semantica tra keyword arguments e argomenti posizionali.

Vengono spesso utilizzati come "opzioni" e forniscono una sintassi molto più leggibile per questa circostanza. Pensate a questo:

>>> sorted([2,-1,3], key=lambda x: x**2, reverse=True) 
[3, 2, -1] 

Versus (python2):

>>> sorted([2,-1,3], None, lambda x: x**2, True) 
[3, 2, -1] 

In questo secondo esempio si può dire che cosa è il significato di None o True?

notare che in chiave solo argomenti, vale a dire gli argomenti che si possono solo specificare utilizzando questa sintassi, sono stati introdotti in python3. In python2 qualsiasi argomento può essere specificato dalla posizione (tranne quando si utilizza **kwargs ma questo è un altro problema).

+0

L'ultima parte di questo è fuorviante. Gli _parametri_ solo per parole chiave sono stati introdotti in Python 3; non esistono argomenti come parole chiave. Ma tutto tranne la nota finale è corretto e ben spiegato. – abarnert

+0

@abarnert Io uso le parole * argomento * e * parametro * come sinonimi. Non vedo perché dovrebbero essere distinti. Ho sempre vissuto con questa ambiguità e non dà alcun problema particolare. In effetti, l'ultimo paragrafo ** chiaramente ** si riferisce a ciò che chiamate * parametri * poiché altrimenti la frase * "argomenti che è possibile specificare solo usando questa sintassi", * non ha alcun significato, quindi non c'è ambiguità. – Bakuriu

+0

Python distingue esplicitamente i due termini. Le domande frequenti su Python hanno [una voce] (http://docs.python.org/3/faq/programming.html#faq-argument-vs-parameter) che spiega perché. Più in generale, ogni lingua ha una tale distinzione ... ma alcuni usano una terminologia diversa (come "parametro attuale" vs. "parametro formale"). Il fatto che a volte puoi farla franca mescolandoli non significa che dovresti; significa che dovresti stare molto attento a non farlo, perché questo ti porterà fuori strada quando ti occupi di casi in cui non puoi farla franca e spesso conduci i tuoi lettori fuori strada anche quando puoi. – abarnert

3

Specificare argomenti per parola chiave crea spesso meno rischi di errore rispetto alla specifica degli argomenti esclusivamente per posizione. Consideriamo questa funzione per calcolare i pagamenti di prestito:

def pmt(principal, interest, term): 
    return **something**; 

Quando si cerca di calcolare l'ammortamento del loro acquisto casa, potrebbe essere invocato così:

payment = pmt(100000, 4.2, 360) 

Ma è difficile vedere quali di questi valori dovrebbe essere associato a quale parametro.Senza verifica della documentazione, potremmo pensare che avrebbe dovuto essere:

payment = pmt(360, 4.2, 100000) 

Uso dei parametri di parole chiave, la chiamata diventa auto-documentazione:

payment = pmt(principal=100000, interest=4.2, term=360) 

Inoltre, i parametri di parole chiave consentono di modificare l'ordine del parametri presso il sito di chiamata, e tutto funziona ancora correttamente:

# Equivalent to previous example 
payment = pmt(term=360, interest=4.2, principal=100000) 

Vedi http://docs.python.org/2/tutorial/controlflow.html#keyword-arguments per ulteriori informazioni.

+0

Elimina i valori predefiniti. –

+3

@SteveBarnes - Precisamente. Ho scritto questa risposta perché gli altri erano focalizzati sui valori di default ... che l'OP non ha mai chiesto. –

Problemi correlati