Existe-t-il un moyen de transmettre des paramètres facultatifs à une fonction?


133

Existe-t-il un moyen en Python de passer des paramètres optionnels à une fonction lors de son appel et dans la définition de la fonction avoir du code basé sur "uniquement si le paramètre optionnel est passé"

Réponses:


115

La documentation Python 2, 7.6. Les définitions de fonction vous offrent plusieurs façons de détecter si un appelant a fourni un paramètre facultatif.

Tout d'abord, vous pouvez utiliser une syntaxe de paramètre formel spéciale *. Si la définition de fonction a un paramètre formel précédé d'un seul *, Python remplit ce paramètre avec tous les paramètres de position qui ne correspondent pas aux paramètres formels précédents (sous forme de tuple). Si la définition de fonction a un paramètre formel précédé de **, Python remplit ce paramètre avec tous les paramètres de mot-clé qui ne correspondent pas aux paramètres formels précédents (sous forme de dict). L'implémentation de la fonction peut vérifier le contenu de ces paramètres pour tout "paramètre facultatif" du type souhaité.

Par exemple, voici une fonction opt_funqui prend deux paramètres de position x1et x2, et recherche un autre paramètre de mot-clé nommé "facultatif".

>>> def opt_fun(x1, x2, *positional_parameters, **keyword_parameters):
...     if ('optional' in keyword_parameters):
...         print 'optional parameter found, it is ', keyword_parameters['optional']
...     else:
...         print 'no optional parameter, sorry'
... 
>>> opt_fun(1, 2)
no optional parameter, sorry
>>> opt_fun(1,2, optional="yes")
optional parameter found, it is  yes
>>> opt_fun(1,2, another="yes")
no optional parameter, sorry

Deuxièmement, vous pouvez fournir une valeur de paramètre par défaut d'une certaine valeur comme Nonecelle qu'un appelant n'utiliserait jamais. Si le paramètre a cette valeur par défaut, vous savez que l'appelant n'a pas spécifié le paramètre. Si le paramètre n'a pas une valeur par défaut, vous savez qu'il provient de l'appelant.


7
positional_parametersest un tuple et keyword_parametersun dictionnaire.
Cees Timmerman

Comment python distingue-t-il formal parameters preceded by * (comment s'appelle-t-il?) D'un keyword parameter? Comme je l'ai compris, les paramètres de mot-clé sont spécifiés à l'aide de l' =opérateur dans l'appel de fonction ( opt_fun(1,2, optional="yes")fournit donc un argument de mot-clé "oui" pour une fonction qui anticipe, mais ne nécessite pas nécessairement, le paramètre option).
Minh Tran

D'un autre côté, j'ai compris formal parameters preceded by * simplement "les arguments fournis par l'appelant qui ne correspondent pas aux arguments positionnels qui précèdent les arguments de mot-clé". Par exemple, dans opt_fun(1,2, "blah", 3.14, mykey="yes", myyear="2018"), "blah"et 3.14sont forma arguments preceded by *parce qu'il est entre les deux arguments de position et l'argument qui utilise le =signe. Le tuple résultant positional_parameterserait le rythme binaire: ("blah", 3.14). Est-ce correct?
Minh Tran

@MinhTran, les questions dans les commentaires ne sont pas le meilleur moyen d'obtenir une réponse dans Stack Overflow. Il est de loin préférable de cliquer sur le gros bouton bleu «Poser une question» et d'écrire votre demande sous forme de «question» à laquelle les autres peuvent «répondre». Mais pour vous aider, a) notez que j'ai écrit " parameter" pas " parameters" pour " preceded by *". La langue n'en autorise qu'un *identifierdans la liste des paramètres. b) lire docs.python.org/2/reference/… , c) lire docs.python.org/2/reference/expressions.html#calls . Désolé, il n'y a plus de caractères autorisés dans ce commentaire.
Jim DeLaHunt

81
def my_func(mandatory_arg, optional_arg=100):
    print(mandatory_arg, optional_arg)

http://docs.python.org/2/tutorial/controlflow.html#default-argument-values

Je trouve cela plus lisible que d'utiliser **kwargs.

Pour déterminer si un argument a été passé du tout, j'utilise un objet utilitaire personnalisé comme valeur par défaut:

MISSING = object()

def func(arg=MISSING):
    if arg is MISSING:
        ...

-Merci, existe-t-il un moyen de spécifier la valeur par défaut de ce paramètre comme une autre variable dans le code?
user1795998

Oui. default_value=100; def my_func(mandatory_argument, optional_argument_with_default_value=default_value): ...
warvariuc

Cela semble montrer comment utiliser des paramètres optionnels, mais pas comment tester si l'un est réussi, ce que demande l'OP.
Mawg dit de réintégrer Monica

4
Dans la plupart des cas, c'est la solution la plus simple et la plus directe que celle de Jim. Si vous définissez la valeur par défaut sur Aucun, vous pouvez vérifier si le paramètre a été transmis ou non. Le seul cas où la solution de Jim est meilleure est s'il est important de faire la distinction entre passer None comme argument et ne pas passer d'argument du tout.
Arnon Axelrod

19
def op(a=4,b=6):
    add = a+b
    print add

i)op() [o/p: will be (4+6)=10]
ii)op(99) [o/p: will be (99+6)=105]
iii)op(1,1) [o/p: will be (1+1)=2]
Note:
 If none or one parameter is passed the default passed parameter will be considered for the function. 

1
Existe-t-il un moyen de ne transmettre que le deuxième paramètre (b) et non le premier (a)?
Djidiouf

4
@Djidiouf Oui, il y aop(b=2)
Jürg Merlin Spaak

7

Si vous voulez donner une valeur par défaut à un paramètre, attribuez une valeur dans (). comme (x = 10). Mais il est important de commencer par l'argument obligatoire puis la valeur par défaut.

par exemple.

(y, x = 10)

mais

(x = 10, y) est faux


Merci, existe-t-il un moyen de spécifier la valeur par défaut de ce paramètre comme une autre variable dans le code?
user1795998

Oui, vous pouvez utiliser quelque chose appelé *arg **kargcomme arguments de fonction. recherche sur Google.
sumit

Cela semble montrer comment utiliser des paramètres optionnels, mais pas comment tester si l'un est réussi, ce que demande l'OP.
Mawg dit de réintégrer Monica

2

Vous pouvez spécifier une valeur par défaut pour l'argument optionnel avec quelque chose qui ne serait jamais passé à la fonction et la vérifier avec l' isopérateur:

class _NO_DEFAULT:
    def __repr__(self):return "<no default>"
_NO_DEFAULT = _NO_DEFAULT()

def func(optional= _NO_DEFAULT):
    if optional is _NO_DEFAULT:
        print("the optional argument was not passed")
    else:
        print("the optional argument was:",optional)

alors tant que vous ne le faites pas, func(_NO_DEFAULT)vous pouvez détecter avec précision si l'argument a été passé ou non, et contrairement à la réponse acceptée, vous n'avez pas à vous soucier des effets secondaires de la notation **:

# these two work the same as using **
func()
func(optional=1)

# the optional argument can be positional or keyword unlike using **
func(1) 

#this correctly raises an error where as it would need to be explicitly checked when using **
func(invalid_arg=7)

Fais juste _NO_DEFAULT = object().
Aran-Fey

2 lignes supplémentaires pour une meilleure introspection en valent la peine. Avec cela, si vous exécutez, help(func)vous obtenez une idée plus claire de la façon dont l'argument est interprété s'il n'est pas passé explicitement.
Tadhg McDonald-Jensen
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.