Prenons pour exemple la fonction toute simple ci-dessous.

def my_func(nom, prenom, age):
    pass

Le language python nous permet de faire appel à elle de trois manières différentes.

my_func("Pannatier", "Guillaume", 29)
my_func(age=29, nom="Pannatier", prenom="Guillaume")
my_func("Pannatier", age=29, prenom="Guillaume")

Petit rappel (*args, **kwargs)

my_func(*["Pannatier", "Guillaume", 29])
my_func(**{"age": 29, "nom": "Pannatier", "prenom": "Guillaume"})
my_func(*["Pannatier"], **{"age": 29, "prenom": "Guillaume"})

Définition :

  • * suivi d’une liste permet de définir les valeurs à passer à la fonction
  • ** suivi d’un dictionnaire permet de définir la valeur par argument à passer à la fonction.

Oui mais

Il n’est pas possible de définir deux fois la valeur pour un argument. Par exemple, l’appel suivant génèrera une exception TypeError.

# Double définition du prénom.
my_func(*["Pannatier", "Guillaume"], **{"prenom": "Guillaume", "age": 29})

Il faut également que tous les arguments aient une valeur. Les appels suivants génèreront aussi une exception TypeError

# Manque la valeur de l'argument age.
my_func(*["Pannatier", "Guillaume"])
# Manque la valeur de l'argument prénom.
my_func(**{"nom": "Guillaume", "age": 29})

Valeur par défaut

Il est tout à fait possible de définir une valeur par défaut pour un argument si cette dernière n’est pas passée lors de l’appel.

def my_func(nom, prenom, age, langue="FR"):
    pass

Inspection

Après cette “courte” introduction, nous voici enfin sur le sujet du post.

Je possède une list et/ou un dictionnaire d’argument à passer à une fonction et j’aimerai :

  • Savoir quels sont les arguments qui manqueront lors de l’appel
  • Savoir quels sont les arguments founis à double qui feront échouer l’appel

J’ai du crééer cette fonction car je devais savoir quels arguments je devais injecter dynamiquement.

import inspect

def inspect_func_call(func, args=[],  kwargs={}):
    f_args, f_vargs, f_vkwargs, f_defaults = inspect.getargspec(func)

    missed_args = []
    multiple_args = []

    if inspect.ismethod(func):
        f_args.pop(0)

    if f_args != None:
        if kwargs and args:
            for arg in f_args[0: len(args)]:
                if arg in kwargs:
                    multiple_args.append(arg)

        missed_args = f_args if not f_defaults else f_args[0:-len(f_defaults)]

        if args:
            missed_args = missed_args[-len(args):]

        for kw in kwargs:
            if kw in missed_args:
                missed_args.remove(kw)

    return missed_args, multiple_args

La fonction ci-dessus retourne un tuple contenant deux listes:

  • missed: La liste des arguments manquants
  • multiple: La liste des arguments doublons


Guillaume Pannatier