Qu'est-ce que l'instruction pass en Python ?

Découvrez l'instruction pass en Python : son rôle, ses cas d'utilisation concrets, ses bonnes pratiques et ses différences avec continue et Ellipsis.
11 min de lecture
Believemy logo

Définition de l'instruction pass en Python

L'instruction pass est un mot-clé réservé de Python qui ne fait absolument rien. C'est une instruction vide (aussi appelée no-op pour "no operation") qui sert de placeholder (espace réservé) dans votre code. Quand Python rencontre pass, il passe simplement à la ligne suivante sans exécuter la moindre opération.

Pourquoi une telle instruction existe-t-elle ? Parce que Python repose sur l'indentation pour définir les blocs de code. Contrairement à d'autres langages qui utilisent des accolades {}, Python exige qu'un bloc indenté contienne au moins une instruction. L'instruction pass permet donc de créer des blocs vides qui sont syntaxiquement valides.

Si vous souhaitez approfondir votre maîtrise de Python et de ses subtilités, notre formation complète sur Python vous accompagnera pas à pas dans votre apprentissage.


Syntaxe et fonctionnement de pass

La syntaxe de pass est la plus simple que vous puissiez imaginer :

PYTHON
pass

C'est tout. Un seul mot. Aucun argument, aucun paramètre, aucune valeur de retour. Quand Python exécute cette instruction, il ne fait strictement rien et passe à l'instruction suivante.

Voyons ce qui se passe si vous essayez de créer un bloc vide sans pass :

PYTHON
# Ceci provoque une erreur de syntaxe
def ma_fonction():
    # Rien ici

print("Bonjour")

Python lèvera une IndentationError ou une SyntaxError car le bloc de la fonction est vide. Avec pass, le problème est résolu :

PYTHON
# Ceci fonctionne parfaitement
def ma_fonction():
    pass

print("Bonjour")
Bon à savoir

pass est une instruction, pas une expression. Vous ne pouvez pas l'utiliser dans un contexte qui attend une valeur, comme une affectation : x = pass provoquerait une erreur de syntaxe.


Cas d'utilisation concrets de pass

L'instruction pass est utilisée dans de nombreuses situations en Python. Passons en revue les cas d'utilisation les plus courants et les plus importants.

Définir des fonctions vides (stubs)

L'un des usages les plus fréquents de pass est la création de fonctions "squelettes" lors de la phase de conception de votre programme. Vous savez que vous aurez besoin d'une fonction, mais vous n'avez pas encore écrit son implémentation :

PYTHON
def calculer_taxe(montant, taux):
    pass

def generer_rapport(donnees):
    pass

def envoyer_notification(utilisateur, message):
    pass

Cette approche est très utile lorsque vous travaillez en équipe ou que vous planifiez l'architecture de votre application. Vous pouvez définir toutes les fonctions nécessaires avec def et revenir les implémenter plus tard, sans que Python ne lève d'erreur.


Créer des classes vides

De la même manière, vous pouvez définir des classes vides avec class et pass. C'est particulièrement utile pour créer des exceptions personnalisées :

PYTHON
# Exceptions personnalisées
class ErreurDeConnexion(Exception):
    pass

class ErreurDeValidation(Exception):
    pass

class UtilisateurNonTrouveErreur(Exception):
    pass

# Utilisation
try:
    raise ErreurDeConnexion("Impossible de se connecter au serveur")
except ErreurDeConnexion as e:
    print(f"Erreur : {e}")

Dans cet exemple, les classes d'exceptions n'ont besoin d'aucune logique supplémentaire : elles héritent simplement de la classe Exception. Le mot-clé pass permet de les déclarer sans contenu.


Ignorer volontairement des exceptions

Parfois, vous souhaitez attraper une exception mais ne rien faire avec. C'est un cas d'utilisation courant (bien qu'il doive être utilisé avec prudence) :

PYTHON
import os

# Supprimer un fichier s'il existe, ignorer l'erreur sinon
try:
    os.remove("fichier_temporaire.txt")
except FileNotFoundError:
    pass
Attention

Attention : ignorer silencieusement des exceptions peut masquer des bugs. N'utilisez cette technique que lorsque vous êtes absolument certain que l'exception peut être ignorée en toute sécurité. Ne faites jamais except Exception: pass qui attraperait toutes les exceptions.


Placeholder dans les boucles

Vous pouvez utiliser pass dans des boucles for ou while lorsque vous développez votre logique progressivement :

PYTHON
# Boucle en cours de développement
for element in ma_liste:
    pass  # TODO: traiter chaque élément

# Boucle while en attente d'implémentation
while condition:
    pass  # TODO: implémenter la logique

C'est également utile avec enumerate lorsque vous planifiez un traitement itératif :

PYTHON
donnees = ["Alice", "Bob", "Charlie"]

for index, nom in enumerate(donnees):
    pass  # TODO: enregistrer chaque utilisateur en base de données


Structures conditionnelles incomplètes

Lors du développement, vous pouvez vouloir esquisser une structure conditionnelle sans implémenter toutes les branches :

PYTHON
def traiter_commande(statut):
    if statut == "en_attente":
        pass  # TODO: envoyer un email de confirmation
    elif statut == "payee":
        pass  # TODO: lancer la préparation
    elif statut == "expediee":
        pass  # TODO: mettre à jour le suivi
    else:
        pass  # TODO: gérer les statuts inconnus


Classes abstraites et interfaces

Bien que Python propose le module abc (Abstract Base Classes) pour les classes abstraites, pass est souvent utilisé pour définir des méthodes que les sous-classes devront implémenter :

PYTHON
class FormeGeometrique:
    def aire(self):
        pass

    def perimetre(self):
        pass

class Rectangle(FormeGeometrique):
    def __init__(self, largeur, hauteur):
        self.largeur = largeur
        self.hauteur = hauteur

    def aire(self):
        return self.largeur * self.hauteur

    def perimetre(self):
        return 2 * (self.largeur + self.hauteur)

class Cercle(FormeGeometrique):
    def __init__(self, rayon):
        self.rayon = rayon

    def aire(self):
        import math
        return math.pi * self.rayon ** 2

    def perimetre(self):
        import math
        return 2 * math.pi * self.rayon

Notez que cette approche ne force pas la sous-classe à implémenter les méthodes. Pour cela, vous devriez utiliser le module abc avec le décorateur @abstractmethod.


Différences entre pass, continue et Ellipsis (...)

Il est fréquent de confondre pass avec d'autres instructions ou objets Python qui semblent proches. Voici un tableau récapitulatif pour clarifier les différences :

InstructionEffetContexte d'utilisation
passNe fait rien du toutN'importe quel bloc de code
continueSaute à l'itération suivanteUniquement dans les boucles
... (Ellipsis)Ne fait rien (c'est un objet)Stubs, type hints, slicing
return NoneTermine la fonction et retourne NoneUniquement dans les fonctions

pass vs continue

La différence fondamentale est que continue affecte le flux d'exécution d'une boucle, tandis que pass ne fait rien :

PYTHON
nombres = [1, 2, 3, 4, 5]

# Avec pass : tous les nombres sont affichés
print("Avec pass :")
for n in nombres:
    if n == 3:
        pass  # Ne fait rien de spécial
    print(n)
# Sortie : 1, 2, 3, 4, 5

print()

# Avec continue : le nombre 3 est sauté
print("Avec continue :")
for n in nombres:
    if n == 3:
        continue  # Saute à l'itération suivante
    print(n)
# Sortie : 1, 2, 4, 5


pass vs Ellipsis (...)

Depuis Python 3, l'objet Ellipsis (représenté par ...) peut aussi servir de placeholder :

PYTHON
# Les deux sont syntaxiquement valides
def fonction_avec_pass():
    pass

def fonction_avec_ellipsis():
    ...

La différence est subtile : pass est une instruction qui ne fait rien, tandis que ... est un objet (de type ellipsis). En pratique, ... est souvent utilisé dans les fichiers de stubs de typage (.pyi) et avec les type hints, tandis que pass est préféré dans le code de production.


Bonnes pratiques avec pass

Voici les bonnes pratiques à suivre lorsque vous utilisez l'instruction pass dans vos projets Python :

1. Toujours ajouter un commentaire explicatif

Quand vous utilisez pass, ajoutez systématiquement un commentaire commentaire qui explique pourquoi le bloc est vide et ce qui devra y être implémenté :

PYTHON
# Mauvais : pass sans explication
def traiter_donnees(donnees):
    pass

# Bon : pass avec un commentaire clair
def traiter_donnees(donnees):
    pass  # TODO: implémenter la validation et le nettoyage des données


2. Préférer les docstrings aux pass dans les fonctions

Si vous créez un stub de fonction, une docstring est souvent préférable car elle documente l'intention de la fonction :

PYTHON
# Acceptable mais pas idéal
def calculer_moyenne(notes):
    pass

# Meilleur : utiliser une docstring
def calculer_moyenne(notes):
    """Calcule la moyenne arithmétique d'une liste de notes.
    
    Args:
        notes: Liste de nombres représentant les notes.
    
    Returns:
        La moyenne des notes sous forme de float.
    """
    pass


3. Ne jamais ignorer toutes les exceptions

L'une des pires pratiques en Python est d'attraper toutes les exceptions avec pass :

PYTHON
# TRÈS MAUVAIS : ne faites jamais ceci !
try:
    resultat = une_operation_complexe()
except:
    pass  # Masque TOUTES les erreurs, y compris KeyboardInterrupt

# MAUVAIS : un peu mieux mais toujours dangereux
try:
    resultat = une_operation_complexe()
except Exception:
    pass  # Masque toutes les exceptions standard

# BON : attraper une exception spécifique
try:
    resultat = une_operation_complexe()
except ValueError:
    pass  # On sait que cette ValueError est attendue et sans conséquence


4. Utiliser pass comme outil temporaire

pass devrait être un outil temporaire dans la plupart des cas. Votre objectif devrait toujours être de remplacer les pass par une implémentation réelle. Certaines équipes utilisent des outils de linting pour détecter les pass restants dans le code :

PYTHON
# Phase de conception : squelette avec pass
class GestionnaireDeCache:
    def __init__(self, taille_max=100):
        pass

    def obtenir(self, cle):
        pass

    def stocker(self, cle, valeur):
        pass

    def invalider(self, cle):
        pass

# Phase d'implémentation : remplacement progressif
class GestionnaireDeCache:
    def __init__(self, taille_max=100):
        self.taille_max = taille_max
        self.cache = {}

    def obtenir(self, cle):
        return self.cache.get(cle)

    def stocker(self, cle, valeur):
        if len(self.cache) >= self.taille_max:
            self.cache.pop(next(iter(self.cache)))
        self.cache[cle] = valeur

    def invalider(self, cle):
        self.cache.pop(cle, None)

Remarquez comment nous avons utilisé dict pour la structure de cache et len pour vérifier la taille.


5. Connaître les alternatives

Selon le contexte, il peut y avoir de meilleures alternatives à pass :

PYTHON
# Au lieu de pass pour une fonction non implémentée :
def fonctionnalite_future():
    raise NotImplementedError("Cette fonctionnalité sera disponible dans la version 2.0")

# Au lieu de pass pour ignorer une exception, utiliser suppress :
from contextlib import suppress

with suppress(FileNotFoundError):
    os.remove("fichier_temporaire.txt")


Exemple complet : projet avec pass

Voici un exemple complet qui illustre l'utilisation de pass dans un processus de développement réaliste, en partant du squelette jusqu'à l'implémentation :

PYTHON
# Étape 1 : Squelette du projet avec pass

class Produit:
    """Représente un produit dans le catalogue."""
    def __init__(self, nom, prix, quantite=0):
        self.nom = nom
        self.prix = prix
        self.quantite = quantite

    def __repr__(self):
        return f"Produit('{self.nom}', {self.prix}€, stock={self.quantite})"


class ErreurStockInsuffisant(Exception):
    pass  # Exception personnalisée pour le stock


class ErreurProduitInexistant(Exception):
    pass  # Exception personnalisée pour les produits inconnus


class Catalogue:
    """Gère le catalogue de produits."""
    def __init__(self):
        self.produits = {}

    def ajouter_produit(self, produit):
        """Ajoute un produit au catalogue."""
        self.produits[produit.nom] = produit

    def rechercher(self, terme):
        """Recherche des produits par nom."""
        resultats = []
        for nom, produit in self.produits.items():
            if terme.lower() in nom.lower():
                resultats.append(produit)
        return resultats

    def appliquer_promotion(self, nom_produit, reduction):
        """Applique une réduction sur un produit."""
        if nom_produit not in self.produits:
            raise ErreurProduitInexistant(f"Produit '{nom_produit}' introuvable")
        produit = self.produits[nom_produit]
        produit.prix *= (1 - reduction / 100)


# Étape 2 : Utilisation
catalogue = Catalogue()
catalogue.ajouter_produit(Produit("Clavier mécanique", 89.99, 50))
catalogue.ajouter_produit(Produit("Souris ergonomique", 49.99, 30))
catalogue.ajouter_produit(Produit("Écran 27 pouces", 349.99, 15))

# Recherche
resultats = catalogue.rechercher("clavier")
for produit in resultats:
    print(produit)

# Gestion d'erreur avec nos exceptions personnalisées
try:
    catalogue.appliquer_promotion("Produit inexistant", 10)
except ErreurProduitInexistant:
    pass  # Attendu dans les tests, on ignore silencieusement

Dans cet exemple, vous pouvez voir que pass est utilisé de manière stratégique : pour les exceptions personnalisées (qui n'ont pas besoin de logique) et pour ignorer une exception attendue. Nous avons aussi utilisé des f-string pour formater les messages.


Questions fréquentes

Question

L'instruction pass affecte-t-elle les performances de mon programme ?

Non, pass n'a absolument aucun impact sur les performances. Le compilateur Python transforme pass en un bytecode NOP (No Operation) qui est exécuté en un temps négligeable. Vous pouvez utiliser autant d'instructions pass que nécessaire sans aucune inquiétude concernant les performances.


Question

Quelle est la différence entre pass et return None dans une fonction ?

pass ne fait rien et l'exécution continue normalement jusqu'à la fin de la fonction (qui retourne implicitement None). return None termine immédiatement la fonction et retourne explicitement None. Si pass est la seule instruction de la fonction, le résultat est identique. Mais si du code suit pass, il sera exécuté, alors que du code après return None ne le sera jamais.


Question

Peut-on utiliser pass en dehors d'un bloc indenté ?

Oui, pass est une instruction valide n'importe où dans votre code Python. Vous pouvez écrire pass seul sur une ligne au niveau global de votre script. Cela n'a aucun effet, mais c'est syntaxiquement valide. Son utilité principale reste cependant à l'intérieur des blocs indentés (fonctions, classes, boucles, conditions).


Question

Comment approfondir ma maîtrise de Python et de ses mots-clés ?

Pour maîtriser Python dans sa globalité, y compris tous ses mots-clés comme pass, lambda, yield ou global, nous vous recommandons de suivre notre formation dédiée à Python sur Believemy. Elle couvre tous les fondamentaux et les concepts avancés avec des exercices pratiques pour progresser rapidement.

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.