105 votes

Obtenir la valeur par défaut de l'argument d'une fonction ?

Pour cette fonction

def eat_dog(name, should_digest=True):
    print "mangé chien nommé %s. Digéré aussi ? %" % (name, str(should_digest))

Je veux, en dehors de la fonction, lire ses arguments et toutes les valeurs par défaut attachées. Donc, pour cet exemple spécifique, je veux savoir que name n'a pas de valeur par défaut (c'est-à-dire que c'est un argument requis) et que True est la valeur par défaut pour should_digest.

Je suis conscient de inspect.getargspec(), qui me donne des informations sur les arguments et les valeurs par défaut, mais je ne vois pas de lien entre les deux:

ArgSpec(args=['name', 'should_digest'], varargs=None, keywords=None, defaults=(True,))

A partir de cette sortie, comment puis-je savoir que True (dans le tuple defaults) est la valeur par défaut pour should_digest?

De plus, je suis conscient du modèle de "demander le pardon" pour aborder un problème, mais malheureusement la sortie de cette erreur ne me dira pas le nom de l'argument manquant:

>>> eat_dog()
Traceback (most recent call last):
  File "", line 1, in 
TypeError: eat_dog() prend au moins 1 argument (0 donné)

Pour donner du contexte (pourquoi je veux faire cela), j'expose des fonctions dans un module via une API JSON. Si l'appelant omet certains arguments de fonction, je veux renvoyer une erreur spécifique qui nomme l'argument de fonction spécifique qui a été omis. Si un client omet un argument, mais qu'il y a une valeur par défaut fournie dans la signature de la fonction, je veux utiliser cette valeur par défaut.

167voto

mgilson Points 92954

Python3.x

Dans un monde python3.x, vous devriez probablement utiliser un objet Signature:

import inspect

def get_default_args(func):
    signature = inspect.signature(func)
    return {
        k: v.default
        for k, v in signature.parameters.items()
        if v.default is not inspect.Parameter.empty
    }

Python2.x (ancienne réponse)

Les args/defaults peuvent être combinés comme suit:

import inspect
a = inspect.getargspec(eat_dog)
zip(a.args[-len(a.defaults):],a.defaults)

Ici, a.args[-len(a.defaults):] sont les arguments avec les valeurs par défaut et évidemment a.defaults sont les valeurs par défaut correspondantes.

Vous pourriez même passer la sortie de zip au constructeur dict et créer une correspondance adaptée pour le déballage des mots-clés.


En regardant la documentation, cette solution ne fonctionnera que sur python2.6 ou plus récent car je suppose que inspect.getargspec renvoie un named tuple. Les versions antérieures renvoyaient un tuple régulier, mais il serait très facile de modifier en conséquence. Voici une version qui fonctionne avec les versions plus anciennes (et plus récentes) :

import inspect
def get_default_args(func):
    """
    renvoie un dictionnaire de nom_arg: valeurs_par_défaut pour la fonction d'entrée
    """
    args, varargs, keywords, defaults = inspect.getargspec(func)
    return dict(zip(args[-len(defaults):], defaults))

À bien y réfléchir :

    return dict(zip(reversed(args), reversed(defaults)))

fonctionnerait également et pourrait être plus intuitif pour certaines personnes.


13voto

Chris_Rands Points 15161

En fonction de ce dont vous avez exactement besoin, vous pourriez ne pas avoir besoin du module inspect puisque vous pouvez vérifier l'attribut __defaults__ de la fonction :

>>> eat_dog.__defaults__
(True,)
>>> eat_dog.__code__.co_argcount
2
>>> eat_dog.__code__.co_varnames
('name', 'should_digest')
>>> 
>>> eat_dog.__kwdefaults__
>>> eat_dog.__code__.co_kwonlyargcount
0

13voto

Eddie Bergman Points 71

A ceux qui cherchent une version pour obtenir un paramètre par défaut spécifique avec la réponse de mgilson.

value = signature(my_func).parameters['param_name'].default

Voici une version complète qui fonctionne, réalisée en Python 3.8.2

from inspect import signature

def my_func(a, b, c, param_name='apple'):
    pass

value = signature(my_func).parameters['param_name'].default

print(value == 'apple') # True

10voto

Tadeck Points 37046

Vous pouvez utiliser le module inspect avec sa fonction getargspec :

inspect.getargspec(func)

Obtenez les noms et valeurs par défaut des arguments d'une fonction Python. Un tuple de quatre éléments est retourné : (args, varargs, keywords, defaults). args est une liste des noms des arguments (elle peut contenir des listes imbriquées). varargs et keywords sont les noms des arguments * et ** ou None. defaults est un tuple des valeurs d'arguments par défaut ou None s'il n'y a pas d'arguments par défaut ; si ce tuple a n éléments, ils correspondent aux derniers n éléments répertoriés dans args.

Voir la réponse de mgilson pour le code exact sur comment récupérer les noms des arguments et leurs valeurs par défaut.

3voto

conmak Points 396

Vous pouvez obtenir ceci via certaines des variables __dunder__ comme mentionné dans d'autres publications. Mettre cela dans une fonction d'aide simple peut vous donner un dictionnaire de valeurs par défaut.

  • .__code__.co_varnames: Un tuple de toutes les variables d'entrée
  • .__defaults__: Un tuple des valeurs par défaut
    • Il est à noter que ce tuple inclut seulement les variables fournies par défaut qui doivent toujours être positionnées en dernier dans les arguments de fonction

Vous pouvez utiliser ces deux éléments pour faire correspondre les dernières variables n dans le .__code__.co_varnames avec tous les éléments dans le .__defaults__

EDIT Merci à @griloHBG - Ajout d'une instruction if pour éviter les exceptions lorsque aucune valeur par défaut n'est spécifiée.

def my_fn(a, b=2, c='a'):
    pass

def get_defaults(fn):
    if fn.__defaults__==None:
        return {}
    return dict(zip(
        fn.__code__.co_varnames[-len(fn.__defaults__):],
        fn.__defaults__
    ))

print(get_defaults(my_fn))

Devrait donner:

{'b': 2, 'c': 'a'}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X