Arguments normaux et arguments de mots clés

289

En quoi les "arguments de mots clés" sont-ils différents des arguments classiques? Tous les arguments ne peuvent-ils pas être passés au name=valuelieu d'utiliser la syntaxe positionnelle?

mk12
la source
6
Vous pourriez également vouloir lire PEP 3102 - ils rangent certains de ces trucs dans Python 3. Voir: python.org/dev/peps/pep-3102
Ben Hoyt
Et qu'il y ait ou non une valeur par défaut n'a rien à voir avec cela (sauf si vous devez ou non lui passer une valeur), n'est-ce pas?
mk12
En savoir plus sur les arguments positionnels / mots-clés de python
ducin
@Ben Hoyt Ajouté une réponse ci-dessous couvrant Python 3, arguments de mots clés requis
Christophe Roussy

Réponses:

346

Il existe deux concepts connexes, tous deux appelés " arguments de mots clés ".

Du côté appelant, ce que d'autres commentateurs ont mentionné, vous avez la possibilité de spécifier certains arguments de fonction par nom. Vous devez les mentionner après tous les arguments sans nom ( arguments positionnels ), et il doit y avoir des valeurs par défaut pour tous les paramètres qui n'ont pas été mentionnés du tout.

L'autre concept est du côté de la définition de fonction: vous pouvez définir une fonction qui prend les paramètres par nom - et vous n'avez même pas besoin de spécifier quels sont ces noms. Ce sont des arguments de mots clés purs et ne peuvent pas être passés de manière positionnelle. La syntaxe est

def my_function(arg1, arg2, **kwargs)

Tous les arguments de mots clés que vous transmettez à cette fonction seront placés dans un dictionnaire nommé kwargs. Vous pouvez examiner les clés de ce dictionnaire au moment de l'exécution, comme ceci:

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

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

{'a': 12, 'b': 'abc'}
Ian Clelland
la source
5
+1 et accepté: vous êtes le seul à avoir parlé des deux types d'arguments positionnels + mots clés, tout le monde pensait que je parlais du premier ou du second (mais ils étaient toujours de bons messages). Merci!
mk12
34
La formulation n'est pas claire: normalement vous parlez d'arguments du côté appelant tandis que de paramètres du côté appelé.
glglgl
3
Le nom du paramètre doit-il être kwargsou je peux le renommer en sth. comme options( def my_fuction(arg1, arg2, **options))?
Bruce Sun
1
Le nom peut être n'importe quoi, mais kwargsc'est la convention quand il n'y a pas de nom plus approprié
Matt Zimmerman
Je pense que le deuxième concept expliqué ici est techniquement appelé arguments de mots-clés arbitraires.
Anshul Dahiya
188

Il y a une dernière fonction linguistique où la distinction est importante. Considérez la fonction suivante:

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

L' *positionalargument stockera tous les arguments de position transmis à foo(), sans limite au nombre que vous pouvez fournir.

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

L' **keywordsargument stockera tous les arguments de mots clés:

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

Et bien sûr, vous pouvez utiliser les deux en même temps:

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

Ces fonctionnalités sont rarement utilisées, mais elles sont parfois très utiles, et il est important de savoir quels arguments sont positionnels ou mots-clés.

trop de php
la source
3
Excellente réponse! Juste une note que les arguments positionnels requis peuvent être passés avant *positionalet **keywordssi nous changeons la définition de fonction comme def foo(arg1, *positional, **keywords):. Voici arg1positionnel et obligatoire. Veuillez noter que positionnel dans la réponse signifie un nombre optionnel et variable d'arguments positionnels.
shaffooo
2
Oui, bonne réponse. Autre remarque: si vous appelez votre fonction, foo(bar=True)vous pouvez obtenir les valeurs en utilisant les bar = keywords.pop('bar')mêmes que bar = keywords.pop('bar', None). Pour la valeur par défaut, utilisezbar = keywords.pop('bar', False)
olibre
111

L'utilisation d'arguments de mots clés est la même chose que les arguments normaux, sauf que l'ordre n'a pas d'importance. Par exemple, les deux appels de fonctions ci-dessous sont identiques:

def foo(bar, baz):
    pass

foo(1, 2)
foo(baz=2, bar=1)
Eli Grey
la source
3
Merci pour cela. Il est incroyablement utile que je puisse à la fois spécifier un argument de mot clé comme argument de position et un argument de position comme argument de mot clé.
Luke Davis
47

Arguments positionnels

Ils n'ont aucun mot clé devant eux. L'ordre est important!

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

Arguments des mots clés

Ils ont des mots clés à l'avant. Ils peuvent être dans n'importe quel ordre!

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

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

Vous devez également savoir que si vous utilisez des arguments par défaut et négligez d'insérer les mots clés, l'ordre importera alors!

def func(foo=1, baz=2, hello=3): ...
func("bar", 5, 123)
Inconnue
la source
8
À mon humble avis, le 3e exemple (arguments par défaut) n'est pas clair. Je pense que vous parlez de ce qui se passe lorsqu'un ou plusieurs paramètres déclarent des valeurs par défaut et que l'appel utilise la notation positionnelle, mais fournit MOINS que le nombre de paramètres déclarés. Cependant, votre exemple a déclaré 3 et 3 dans l'appel, donc les valeurs par défaut n'ont aucun effet! Aviez-vous l'intention d'omettre le troisième argument? par exemple func("bar", 5)? Et puis dire que helloobtient sa valeur par défaut de 3.
ToolmakerSteve
25

Il existe deux façons d'affecter des valeurs d'argument aux paramètres de fonction, les deux sont utilisées.

  1. Par position. Les arguments positionnels n'ont pas de mots clés et sont attribués en premier.

  2. Par mot-clé. Les arguments de mot-clé ont des mots-clés et sont attribués en second, après les arguments de position.

Notez que vous avez la possibilité d'utiliser des arguments positionnels.

Si vous n'utilisez pas d'arguments positionnels, alors - oui - tout ce que vous avez écrit se révèle être un argument mot-clé.

Lorsque vous appelez une fonction, vous décidez d'utiliser la position, le mot-clé ou un mélange. Vous pouvez choisir de faire tous les mots clés si vous le souhaitez. Certains d'entre nous ne font pas ce choix et utilisent des arguments positionnels.

S.Lott
la source
1
Ohh, je pensais ça aux paramètres, quand ce sont en fait les arguments (ce que je passe). Merci!
mk12
24

Je suis surpris que personne ne semble avoir souligné que l'on peut passer un dictionnaire de paramètres d'argument à clé, qui satisfont les paramètres formels, comme ça.

>>> 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
>>> 
Sherman
la source
11
+1 pour une technique utile. Votre point serait plus clair, sans , **kwargs. Cela démontrerait que même une simple fonction func, avec un nombre fixe de paramètres, peut être fournie avec un dictionnaire. Autrement dit, il ne nécessite rien d'extraordinaire dans la définition. ALORS, vous pouvez ajouter un deuxième exemple, AVEC ** kwargs dans la définition, et montrer comment les éléments EXTRA dans le dictionnaire sont disponibles via cela.
ToolmakerSteve
1
J'ai vu cela se produire dans le code source de diverses bibliothèques et j'étais tellement confus. Merci de l'avoir éclairci!
Craig Labenz
3
Le quatrième paramètre formel ci-dessus - ** kwargs est nécessaire si vous appelez func avec un dictionnaire qui contient des clés autres que «a», «b» et «c».
Eduardo
Pour moi, print 'a:%s, b:%s, c:%s' % (a, b, c)donne une erreur de syntaxe, mais print('a:%s, b:%s, c:%s' % (a, b, c))fonctionne. Quelque chose avec la version Python? Quoi qu'il en soit, merci pour cette idée, jusqu'à présent, j'utilisais le plus maladroitprint('a:{}, b:{}, c:{}'.format(a, b, c))
Axel Bregnsbo
17

En utilisant Python 3, vous pouvez avoir à la fois des arguments de mots clés requis et non requis :


Facultatif : (valeur par défaut définie pour le paramètre 'b')

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

Obligatoire (aucune valeur par défaut définie pour le paramètre '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'`

Cela peut aider dans les cas où vous avez de nombreux arguments similaires les uns à côté des autres, surtout s'ils sont du même type, dans ce cas, je préfère utiliser des arguments nommés ou je crée une classe personnalisée si les arguments vont de pair.

Christophe Roussy
la source
3
La variante requise est très utile. Il exhorte à donner les arguments par leur nom sans fournir de valeurs par défaut, ce qui n'a souvent aucun sens.
TNT
Les valeurs par défaut sont agréables et peuvent vous aider à gagner du temps lorsque vous démarrez, mais à long terme, les valeurs par défaut peuvent être un PITA.
Christophe Roussy
11

Je suis surpris que personne n'ait mentionné le fait que vous pouvez mélanger des arguments de position et de mots clés pour faire des choses sournoises comme celle-ci en utilisant *argset **kwargspartir de ce site ):

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

Cela vous permet d'utiliser des arguments de mots clés arbitraires qui peuvent avoir des clés que vous ne souhaitez pas définir à l'avance.

Gabriel Hurley
la source
0

Je cherchais un exemple qui avait des kwargs par défaut en utilisant l'annotation de type:

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

exemple:

>>> 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 {}
jmunsch
la source
0

Il suffit de compléter / ajouter un moyen de définir la valeur par défaut des arguments qui ne sont pas attribués en mots clés lors de l'appel de la fonction:

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

appelez cela par:

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

tu auras:

default_msg
love

en savoir plus sur *argset **kwargsen python: https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3

sonictl
la source