2008-11-01 16 views
12

Je voudrais savoir s'il est possible de déterminer si un paramètre de fonction avec une valeur par défaut a été passé en Python. Par exemple, comment fonctionne dict.pop?Déterminer si un paramètre nommé a été passé

>>> {}.pop('test') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
KeyError: 'pop(): dictionary is empty' 
>>> {}.pop('test',None) 
>>> {}.pop('test',3) 
3 
>>> {}.pop('test',NotImplemented) 
NotImplemented 

Comment la méthode pop déterminer que la première fois une valeur de retour par défaut n'a pas été adopté? Est-ce quelque chose qui ne peut être fait qu'en C?

Merci

Répondre

7

Je suppose que vous voulez dire "argument mot-clé", quand vous dites "paramètre nommé". dict.pop() n'accepte pas l'argument mot-clé, donc cette partie de la question est discutable.

>>> {}.pop('test', d=None) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: pop() takes no keyword arguments 

Cela dit, la façon de détecter si un argument a été fourni est d'utiliser la syntaxe *args ou **kwargs. Par exemple:

def foo(first, *rest): 
    if len(rest) > 1: 
     raise TypeError("foo() expected at most 2 arguments, got %d" 
         % (len(rest) + 1)) 
    print 'first =', first 
    if rest: 
     print 'second =', rest[0] 

Avec un peu de travail, et en utilisant la syntaxe **kwargs aussi, il est possible d'émuler complètement la convention d'appel python, où les arguments peuvent être fournis soit par la position ou par nom, et les arguments fournis à plusieurs reprises (par position et nom) provoquent une erreur.

1

Vous pouvez le faire comme ceci:

def isdefarg(*args): 
    if len(args) > 0: 
     print len(args), "arguments" 
    else: 
     print "no arguments" 

isdefarg() 
isdefarg(None) 
isdefarg(5, 7) 

Voir la documentation Python sur calls pour une information complète.

1
def f(one, two=2): 
    print "I wonder if", two, "has been passed or not..." 

f(1, 2) 

Si tel est le sens exact de votre question, je pense qu'il n'y a pas moyen de distinguer entre un 2 qui était dans la valeur par défaut et 2 qui a été adoptée. Je n'ai pas trouvé comment faire une telle distinction, même dans le module inspect.

1

Je ne suis pas certain si je comprends parfaitement ce que vous voulez; cependant:

def fun(arg=Ellipsis): 
    if arg is Ellipsis: 
     print "No arg provided" 
    else: 
     print "arg provided:", repr(arg) 

fait-il ce que vous voulez? Si non, alors comme d'autres l'ont suggéré, vous devez déclarer votre fonction avec la syntaxe *args, **kwargs et vérifier le dict kwargs pour l'existence du paramètre.

11

La convention est souvent d'utiliser arg=None et utiliser

def foo(arg=None): 
    if arg is None: 
     arg = "default value" 
     # other stuff 
    # ... 

pour vérifier si elle a été adoptée ou non. Autoriser l'utilisateur à passer None, ce qui serait interprété comme si l'argument était pas transmis.

+5

Cela n'est pas utile si 'None' est également une valeur significative pour le paramètre. L'exemple est 'dict.pop' et son comportement quand la clé n'est pas trouvée - il retourne le deuxième paramètre s'il est présent, ou soulève KeyError autrement. – Kos

+5

Dans ce cas, vous pouvez créer une variable de fermeture avec un objet. 'MISSING = objet(); def foo (arg = MISSING): si arg est manquant: ... ' –

Questions connexes