Argomenti normali e argomenti di parole chiave


289

In che modo gli "argomenti di parole chiave" sono diversi dagli argomenti normali? Non è possibile passare tutti gli argomenti come name=valueanziché utilizzare la sintassi posizionale?


6
Potresti anche leggere PEP 3102 - stanno sistemando alcune di queste cose in Python 3. Vedi: python.org/dev/peps/pep-3102
— Ben Hoyt

E se un valore predefinito esiste o meno non ha nulla a che fare con esso (tranne se è necessario passarlo o meno), giusto?
— MK

Maggiori informazioni sugli argomenti posizionali / parole chiave di
— Python

@Ben Hoyt Aggiunta di seguito una risposta riguardante Python 3, argomenti delle parole chiave richiesti
— Christophe Roussy,

Risposte:


346

Esistono due concetti correlati, entrambi chiamati " argomenti di parole chiave ".

Sul lato chiamante, che è quello che altri commentatori hanno menzionato, hai la possibilità di specificare alcuni argomenti di funzione per nome. Devi menzionarli dopo tutti gli argomenti senza nome ( argomenti posizionali ) e devono esserci valori predefiniti per tutti i parametri che non sono stati menzionati affatto.

L'altro concetto è sul lato della definizione della funzione: è possibile definire una funzione che accetta i parametri per nome e non è nemmeno necessario specificare quali sono quei nomi. Questi sono argomenti di parole chiave puri e non possono essere passati in posizione. La sintassi è

def my_function(arg1, arg2, **kwargs)

Qualsiasi argomento di parole chiave che passi a questa funzione verrà inserito in un dizionario chiamato kwargs. Puoi esaminare le chiavi di questo dizionario in fase di esecuzione, in questo modo:

def my_function(**kwargs):
    print str(kwargs)

my_function(a=12, b="abc")

{'a': 12, 'b': 'abc'}

5
+1 e accettato: sei l'unico che ha parlato di entrambi i tipi di argomenti posizionali + parole chiave, tutti gli altri pensavano che stessi parlando del primo o del secondo (ma erano comunque buoni post). Grazie!
— MK

34
La formulazione non è chiara: normalmente si parla di argomenti sul lato chiamante mentre di parametri sul lato chiamato.
— glglgl

3
Il nome del parametro deve essere kwargso posso rinominarlo in sth. come options( def my_fuction(arg1, arg2, **options))?
— Bruce Sun

1
Il nome può essere qualsiasi cosa, sebbene kwargssia la convenzione quando non esiste un nome più appropriato
— Matt Zimmerman,

Penso che il secondo concetto spiegato qui sia tecnicamente chiamato Argomenti per parole chiave arbitrarie.
— Anshul Dahiya il

188

C'è un'ultima caratteristica della lingua in cui la distinzione è importante. Considera la seguente funzione:

def foo(*positional, **keywords):
    print "Positional:", positional
    print "Keywords:", keywords

L' *positionalargomento memorizzerà tutti gli argomenti posizionali passati foo(), senza limiti a quanti ne puoi fornire.

>>> foo('one', 'two', 'three')
Positional: ('one', 'two', 'three')
Keywords: {}

L' **keywordsargomento memorizzerà tutti gli argomenti delle parole chiave:

>>> foo(a='one', b='two', c='three')
Positional: ()
Keywords: {'a': 'one', 'c': 'three', 'b': 'two'}

E, naturalmente, è possibile utilizzare entrambi contemporaneamente:

>>> foo('one','two',c='three',d='four')
Positional: ('one', 'two')
Keywords: {'c': 'three', 'd': 'four'}

Queste funzionalità vengono utilizzate raramente, ma a volte sono molto utili ed è importante sapere quali argomenti sono posizionali o parole chiave.


3
Risposta eccellente! Solo una nota che gli argomenti posizionali richiesti possono essere passati prima *positionale **keywordsse cambiamo la definizione della funzione come def foo(arg1, *positional, **keywords):. Qui arg1è posizionale e richiesto. Si noti che posizionale nella risposta indica un numero facoltativo e variabile di argomenti posizionali.
— Shaffooo,

2
Sì, bella risposta. Un'altra nota: se chiami la tua funzione foo(bar=True)puoi ottenere i valori usando lo bar = keywords.pop('bar')stesso di bar = keywords.pop('bar', None). Per valore predefinito, utilizzarebar = keywords.pop('bar', False)
— olibre il

111

L'uso degli argomenti delle parole chiave è la stessa cosa degli argomenti normali, tranne per il fatto che l'ordine non ha importanza. Ad esempio le due funzioni chiamate di seguito sono le stesse:

def foo(bar, baz):
    pass

foo(1, 2)
foo(baz=2, bar=1)

3
Grazie per questo. È incredibilmente utile che sia sia possibile specificare una parola chiave arg come arg posizionale, sia un'arg posizionale come arg parola chiave.
— Luke Davis,

47

Argomenti posizionali

Non hanno parole chiave prima di loro. L'ordine è importante!

func(1,2,3, "foo")

Argomenti di parole chiave

Hanno parole chiave nella parte anteriore. Possono essere in qualsiasi ordine!

func(foo="bar", baz=5, hello=123)

func(baz=5, foo="bar", hello=123)

Dovresti anche sapere che se usi argomenti predefiniti e trascuri per inserire le parole chiave, l'ordine avrà importanza!

def func(foo=1, baz=2, hello=3): ...
func("bar", 5, 123)

8
IMHO, il terzo esempio (argomenti predefiniti) non è chiaro. Penso che tu stia parlando di cosa succede quando uno o più parametri dichiarano valori predefiniti e la chiamata usa la notazione posizionale, ma fornisce MENO del numero di parametri dichiarati. Tuttavia, nel tuo esempio sono stati dichiarati 3 e 3 nella chiamata, quindi i valori predefiniti non hanno alcun effetto! Hai intenzione di omettere il terzo argomento. ad es func("bar", 5). E poi dire che helloottiene il suo valore predefinito di 3.
— ToolmakerSteve

25

Esistono due modi per assegnare i valori degli argomenti ai parametri della funzione, entrambi vengono utilizzati.

  1. Per posizione. Gli argomenti posizionali non hanno parole chiave e vengono assegnati per primi.

  2. Per parola chiave. Gli argomenti delle parole chiave hanno parole chiave e vengono assegnati in secondo luogo, dopo gli argomenti posizionali.

Nota che hai la possibilità di usare argomenti posizionali.

Se si non si utilizza argomenti posizionali, poi - sì - tutto quello che si ha scritto si rivela essere un argomento parola chiave.

Quando si chiama una funzione, si decide di utilizzare la posizione, la parola chiave o una combinazione. Puoi scegliere di utilizzare tutte le parole chiave, se lo desideri. Alcuni di noi non fanno questa scelta e usano argomenti posizionali.


1
Ohh, stavo pensando a quello dei parametri, quando ciò che realmente è sono gli argomenti (ciò che passo). Grazie!
— MK

24

Sono sorpreso che nessuno sembra aver sottolineato che si può passare un dizionario di parametri di argomenti chiave, che soddisfano i parametri formali, in questo modo.

>>> def func(a='a', b='b', c='c', **kwargs):
...    print 'a:%s, b:%s, c:%s' % (a, b, c)
... 
>>> func()
a:a, b:b, c:c
>>> func(**{'a' : 'z', 'b':'q', 'c':'v'})
a:z, b:q, c:v
>>> 

11
+1 per una tecnica utile. Il tuo punto sarebbe più chiaro, senza , **kwargs. Ciò dimostrerebbe che è possibile fornire un dizionario anche a una semplice funzione, con un numero fisso di parametri. Cioè, non richiede nulla di speciale nella definizione. POI potresti aggiungere un secondo esempio, CON ** kwargs nella definizione, e mostrare come gli elementi EXTRA nel dizionario sono disponibili tramite quello.
— ToolmakerSteve

1
L'ho visto accadere nel codice sorgente di varie librerie ed ero così confuso. Grazie per averlo chiarito!
— Craig Labenz,

3
Il quarto parametro formale sopra - ** kwargs è necessario se chiamate mai func con un dizionario che contiene chiavi diverse da 'a', 'b' e 'c'.
— Eduardo,

Per me print 'a:%s, b:%s, c:%s' % (a, b, c)dà errore di sintassi, tuttavia print('a:%s, b:%s, c:%s' % (a, b, c))funziona. Qualcosa con la versione di Python? Comunque grazie per questa intuizione, fino ad ora stavo usando il più goffoprint('a:{}, b:{}, c:{}'.format(a, b, c))
— Axel Bregnsbo il

17

Usando Python 3 puoi avere argomenti di parole chiave sia obbligatori che non obbligatori :


Opzionale : (valore predefinito definito per param 'b')

def func1(a, *, b=42):
    ...
func1(value_for_a) # b is optional and will default to 42

Richiesto (nessun valore predefinito definito per param 'b'):

def func2(a, *, b):
    ... 
func2(value_for_a, b=21) # b is set to 21 by the function call
func2(value_for_a) # ERROR: missing 1 required keyword-only argument: 'b'`

Questo può aiutare nei casi in cui hai molti argomenti simili uno accanto all'altro, specialmente se sono dello stesso tipo, in quel caso preferisco usare argomenti con nome o creo una classe personalizzata se gli argomenti appartengono insieme.


3
La variante richiesta è abbastanza utile. Esorta a dare gli argomenti per nome senza fornire le impostazioni predefinite, il che spesso non ha senso.
— TNT,

I valori predefiniti hanno un bell'aspetto e possono aiutarti a risparmiare tempo quando inizi, ma a lungo termine i valori predefiniti possono essere una PITA.
— Christophe Roussy,

11

Sono sorpreso che nessuno abbia menzionato il fatto che puoi mescolare argomenti posizionali e parole chiave per fare cose subdole come questa usando *argse **kwargs( da questo sito ):

def test_var_kwargs(farg, **kwargs):
    print "formal arg:", farg
    for key in kwargs:
        print "another keyword arg: %s: %s" % (key, kwargs[key])

Ciò consente di utilizzare argomenti di parole chiave arbitrari che potrebbero avere chiavi che non si desidera definire in anticipo.


0

Stavo cercando un esempio che avesse kwargs predefiniti usando l'annotazione di tipo:

def test_var_kwarg(a: str, b: str='B', c: str='', **kwargs) -> str:
     return ' '.join([a, b, c, str(kwargs)])

esempio:

>>> print(test_var_kwarg('A', c='okay'))
A B okay {}
>>> d = {'f': 'F', 'g': 'G'}
>>> print(test_var_kwarg('a', c='c', b='b', **d))
a b c {'f': 'F', 'g': 'G'}
>>> print(test_var_kwarg('a', 'b', 'c'))
a b c {}

0

Basta implementare / aggiungere un modo per definire il valore predefinito degli argomenti che non è assegnato nelle parole chiave quando si chiama la funzione:

def func(**keywargs):
if 'my_word' not in keywargs:
    word = 'default_msg'
else:
    word = keywargs['my_word']
return word

chiamalo come segue:

print(func())
print(func(my_word='love'))

otterrai:

default_msg
love

leggi di più su *argse **kwargsin python: https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3

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.