Qu'est-ce que *args en Python ? Définition et exemples

Découvrez *args en Python : syntaxe, fonctionnement et exemples pratiques pour passer un nombre variable d'arguments positionnels à une fonction.
9 min de lecture
Believemy logo

Définition de *args en Python

En Python, *args est une convention syntaxique utilisée dans la définition d'une def pour permettre à cette fonction d'accepter un nombre variable d'arguments positionnels. L'astérisque * est l'opérateur de décompression (unpacking), et args est simplement un nom conventionnel — vous pourriez techniquement utiliser n'importe quel autre nom, comme *valeurs ou *elements, mais la convention *args est universellement adoptée par la communauté Python.

Lorsque vous utilisez *args dans la signature d'une fonction, Python regroupe automatiquement tous les arguments positionnels supplémentaires dans un tuple. Cela signifie que vous pouvez appeler votre fonction avec zéro, un, dix ou même cent arguments sans modifier sa définition.

Si vous souhaitez maîtriser ce concept et bien d'autres fondamentaux du langage, nous vous recommandons de suivre notre formation complète sur Python qui couvre en profondeur les mécanismes de fonctions avancées.

Bon à savoir

*args collecte les arguments positionnels sous forme de tuple. Pour collecter des arguments nommés (mot-clé), on utilise **kwargs (keyword arguments).


Syntaxe de base de *args

La syntaxe de *args est simple : il suffit de placer un astérisque * devant le nom du paramètre dans la définition de la fonction.

PYTHON
def ma_fonction(*args):
    print(type(args))  # <class 'tuple'>
    for arg in args:
        print(arg)

ma_fonction(1, 2, 3)
# 1
# 2
# 3

Dans cet exemple, les trois arguments 1, 2 et 3 sont automatiquement regroupés dans le tuple (1, 2, 3) accessible via la variable args.


Exemples pratiques d'utilisation de *args

Fonction de somme avec un nombre variable d'arguments

L'un des cas d'utilisation les plus classiques de *args est la création d'une fonction capable d'additionner un nombre quelconque de valeurs :

PYTHON
def somme(*args):
    total = 0
    for nombre in args:
        total += nombre
    return total

print(somme(1, 2))           # 3
print(somme(10, 20, 30))     # 60
print(somme(5))              # 5
print(somme())               # 0

Remarquez que la fonction fonctionne même sans argument : dans ce cas, args est simplement un tuple vide ().


Combiner des paramètres classiques et *args

Vous pouvez parfaitement combiner des paramètres classiques avec *args. Les paramètres classiques sont remplis en premier, et le reste des arguments est capturé par *args :

PYTHON
def saluer(salutation, *args):
    for nom in args:
        print(f"{salutation}, {nom} !")

saluer("Bonjour", "Alice", "Bob", "Charlie")
# Bonjour, Alice !
# Bonjour, Bob !
# Bonjour, Charlie !

Ici, "Bonjour" est capturé par le paramètre salutation, et les trois noms suivants sont regroupés dans args sous la forme ("Alice", "Bob", "Charlie"). Notez l'utilisation des f-string pour formater la sortie.


Utiliser *args pour transmettre des arguments à une autre fonction

Un usage très courant de *args est la transmission d'arguments (forwarding) d'une fonction à une autre. C'est particulièrement utile pour créer des fonctions enveloppantes (wrappers) ou des décorateurs :

PYTHON
def journaliser(func, *args):
    print(f"Appel de {func.__name__} avec les arguments : {args}")
    resultat = func(*args)
    print(f"Résultat : {resultat}")
    return resultat

def multiplier(a, b):
    return a * b

journaliser(multiplier, 4, 5)
# Appel de multiplier avec les arguments : (4, 5)
# Résultat : 20

Observez que *args est utilisé deux fois : une première fois pour collecter les arguments dans le tuple args, et une seconde fois avec func(*args) pour décompresser ce tuple et passer chaque élément comme argument individuel à func.


Créer un décorateur avec *args et **kwargs

Les décorateurs sont l'un des cas d'utilisation les plus puissants de *args. En combinant *args et **kwargs, vous pouvez créer un décorateur qui fonctionne avec n'importe quelle fonction, peu importe sa signature :

PYTHON
import time

def mesurer_temps(func):
    def wrapper(*args, **kwargs):
        debut = time.time()
        resultat = func(*args, **kwargs)
        fin = time.time()
        print(f"{func.__name__} a pris {fin - debut:.4f} secondes")
        return resultat
    return wrapper

@mesurer_temps
def calculer_somme(*args):
    return sum(args)

calculer_somme(1, 2, 3, 4, 5)
# calculer_somme a pris 0.0000 secondes


Décompression d'une liste ou d'un tuple avec *

L'opérateur * ne sert pas uniquement dans les définitions de fonctions. Vous pouvez aussi l'utiliser pour décompresser une list ou un tuple lors de l'appel d'une fonction :

PYTHON
def afficher_coordonnees(x, y, z):
    print(f"x={x}, y={y}, z={z}")

coordonnees = [10, 20, 30]
afficher_coordonnees(*coordonnees)
# x=10, y=20, z=30

# Fonctionne aussi avec un tuple
point = (5, 15, 25)
afficher_coordonnees(*point)
# x=5, y=15, z=25


Décompression étendue dans les assignations

Depuis Python 3, l'opérateur * peut également être utilisé dans les assignations de variables pour capturer plusieurs éléments :

PYTHON
premier, *milieu, dernier = [1, 2, 3, 4, 5]
print(premier)   # 1
print(milieu)    # [2, 3, 4]
print(dernier)   # 5

tete, *queue = "Python"
print(tete)      # P
print(queue)     # ['y', 't', 'h', 'o', 'n']
Attention

Attention : dans une assignation avec *, la variable étoilée reçoit toujours une liste (et non un tuple comme dans *args).


Ordre des paramètres dans une fonction Python

Lorsque vous combinez différents types de paramètres, l'ordre est strict et doit être respecté. Voici l'ordre attendu par Python :

PositionType de paramètreExemple
1Paramètres positionnels classiquesa, b
2*args*args
3Paramètres nommés obligatoires (après *)clef
4**kwargs**kwargs

Voici un exemple illustrant cet ordre complet :

PYTHON
def fonction_complete(a, b, *args, option=True, **kwargs):
    print(f"a = {a}")
    print(f"b = {b}")
    print(f"args = {args}")
    print(f"option = {option}")
    print(f"kwargs = {kwargs}")

fonction_complete(1, 2, 3, 4, 5, option=False, nom="test", valeur=42)
# a = 1
# b = 2
# args = (3, 4, 5)
# option = False
# kwargs = {'nom': 'test', 'valeur': 42}
Attention

Ne placez jamais *args avant les paramètres positionnels classiques, car cela provoquerait une erreur ou un comportement inattendu.


Différences entre *args et **kwargs

Il est essentiel de bien comprendre la distinction entre *args et **kwargs, car ces deux mécanismes sont complémentaires :

Caractéristique*args**kwargs
CollecteArguments positionnelsArguments nommés (mot-clé)
Type résultanttupledict
Syntaxe d'appelf(1, 2, 3)f(a=1, b=2)
Décompression*mon_tuple**mon_dict

Les deux peuvent être utilisés ensemble, comme nous l'avons vu dans l'exemple du décorateur. Ensemble, ils permettent de créer des fonctions extrêmement flexibles capables de recevoir n'importe quelle combinaison d'arguments. Le dict résultant de **kwargs est particulièrement utile pour traiter des options de configuration.


Bonnes pratiques avec *args

Voici les recommandations à suivre pour utiliser *args de manière efficace et maintenable :

  • Respectez la convention de nommage : utilisez *args et non un autre nom, sauf si un nom plus descriptif améliore réellement la lisibilité (comme *nombres pour une fonction mathématique).
  • Documentez votre fonction : lorsque vous utilisez *args, ajoutez une docstring claire expliquant quels types d'arguments sont attendus et en quelle quantité.
  • Validez les entrées : puisque *args accepte tout, pensez à vérifier le type et le nombre des arguments reçus si nécessaire.
  • N'abusez pas de *args : si votre fonction attend toujours exactement deux ou trois arguments, utilisez des paramètres nommés explicites. *args doit être réservé aux cas où le nombre d'arguments est réellement variable.
  • Préférez les annotations de type : depuis Python 3.11+, vous pouvez annoter *args avec *args: int pour indiquer le type attendu de chaque argument.
PYTHON
def moyenne(*args: float) -> float:
    """Calcule la moyenne d'un nombre variable de valeurs.
    
    Args:
        *args: Les valeurs numériques dont on souhaite
               calculer la moyenne.
    
    Returns:
        La moyenne arithmétique des valeurs.
    
    Raises:
        ValueError: Si aucune valeur n'est fournie.
    """
    if not args:
        raise ValueError("Au moins une valeur est requise")
    return sum(args) / len(args)

print(moyenne(10, 20, 30))  # 20.0

Notez l'utilisation de la fonction len pour obtenir le nombre d'éléments du tuple args.


Cas d'utilisation courants de *args

Voici les situations les plus fréquentes où *args se révèle indispensable :

  • Décorateurs : pour créer des décorateurs génériques qui fonctionnent avec n'importe quelle fonction.
  • Fonctions mathématiques : somme, produit, moyenne, minimum, maximum sur un nombre variable de valeurs.
  • Héritage de class : pour transmettre les arguments au constructeur de la classe parente avec super().__init__(*args).
  • Wrappers et proxies : pour encapsuler un appel de fonction tout en transmettant fidèlement ses arguments.
  • Fonctions d'affichage : la fonction print de Python elle-même utilise *args pour accepter un nombre variable d'objets à afficher.
  • Concaténation de collections : fusionner plusieurs listes, tuples ou sets passés en arguments.


Erreurs courantes à éviter

Voici les pièges les plus fréquents liés à l'utilisation de *args :

Oublier l'astérisque lors de la décompression

PYTHON
def afficher(a, b, c):
    print(a, b, c)

valeurs = (1, 2, 3)

# Erreur : passe le tuple entier comme premier argument
# afficher(valeurs)  # TypeError

# Correct : décompresse le tuple
afficher(*valeurs)  # 1 2 3


Confondre *args (tuple) et une liste

PYTHON
def modifier(*args):
    # args est un tuple, donc immuable
    # args[0] = 10  # TypeError: 'tuple' does not support item assignment
    
    # Convertir en liste si modification nécessaire
    args_liste = list(args)
    args_liste[0] = 10
    return args_liste

print(modifier(1, 2, 3))  # [10, 2, 3]


Placer *args après **kwargs

PYTHON
# ERREUR DE SYNTAXE :
# def mauvais(**kwargs, *args):  # SyntaxError
#     pass

# CORRECT :
def correct(*args, **kwargs):
    pass


Questions fréquentes

Question

Est-ce que le nom "args" est obligatoire en Python ?

Non, le nom args n'est pas obligatoire. C'est l'astérisque * qui donne le comportement de collecte des arguments positionnels. Vous pourriez écrire *nombres, *elements ou tout autre nom valide. Cependant, *args est une convention très forte dans la communauté Python (définie dans la PEP 8), et la respecter rend votre code immédiatement compréhensible par les autres développeurs.


Question

Peut-on utiliser *args avec des annotations de type ?

Oui, depuis Python 3.11 (PEP 646), vous pouvez annoter *args directement. Par exemple, def ma_fonction(*args: int) indique que tous les arguments collectés doivent être de type int. Avant Python 3.11, vous pouviez utiliser typing.Tuple ou typing.Any pour des annotations plus complexes. Ces annotations n'ont pas d'effet à l'exécution, mais elles sont exploitées par les outils d'analyse statique comme mypy.


Question

Quelle est la différence entre *args dans une définition et dans un appel de fonction ?

Dans une définition de fonction (def f(*args)), l'opérateur * collecte (pack) les arguments positionnels dans un tuple. Dans un appel de fonction (f(*ma_liste)), l'opérateur * décompresse (unpack) un itérable en arguments individuels. Ce sont deux opérations inverses qui utilisent la même syntaxe.


Question

Comment apprendre à maîtriser *args et les fonctions avancées en Python ?

Pour approfondir votre compréhension de *args, **kwargs, des décorateurs et de toutes les subtilités des fonctions en Python, nous vous recommandons de suivre notre formation Python sur Believemy. Vous y trouverez des exercices pratiques, des projets concrets et un accompagnement pédagogique complet pour maîtriser ces concepts essentiels du développement Python.

Termes connexes

Découvrez notre glossaire Python

Parcourez les termes et définitions les plus couramment utilisés dans le domaine du développement avec Python.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.