Classes et objets Python : didacticiel POO avec des exemples réels

  1. Accueil
  2. Blog
  3. Développement de logiciels

Développement de logiciels

Classes et objets Python : Tutoriel POO avec des exemples réels

Apprenez Python orienté objet en construisant quelque chose de réel. Créez des classes, comprenez vous-même et __init__, partagez votre comportement avec l’héritage, protégez les données avec des propriétés et sachez quand une classe n’est pas le bon outil.

10 min de lecture
Classes et objets Python : tutoriel POO avec exemples réels

À retenir

  • Une classe est un modèle, et un objet est une chose construite à partir de celui-ci.
  • __init__ configure chaque nouvel objet et self fait référence à cet objet.
  • Les attributs définis sur la classe sont partagés. Les attributs définis sur self appartiennent à un seul objet.
  • Utilisez @dataclass pour les classes détenant des données et préférez les fonctions simples lorsqu’il n’y a pas d’état à conserver.

Au fur et à mesure qu’un script grandit, vous finissez par transmettre le même groupe de variables entre les fonctions, et il devient difficile de savoir quelles données appartiennent à quelle logique. Les classes et objets Python résolvent ce problème en regroupant les données et le comportement en une seule unité.

Dans ce didacticiel, nous construisons un petit compte bancaire étape par étape et ajoutons chaque idée de POO uniquement lorsqu’elle résout un problème. Nous avons exécuté chaque exemple sur Python 3.13 et le résultat affiché provient de cette exécution. Si vous êtes nouveau dans le langage, lisez d’abord notre Tutoriel Python pour débutants.

Que sont les classes et les objets ?

Une classe décrit ce qu’est quelque chose et ce qu’il peut faire. Un objet, également appelé instance, est un objet spécifique créé à partir de cette description. « Compte » est une classe, tandis que le compte d’Asha et le compte de Ben sont deux objets.

Durée Signification Exemple
Classe Le plan Compte
Objet ou instance Une chose faite à partir de ça a = Compte("Asha")
Attribut Données sur l’objet a.balance
Méthode Une fonction sur la classe a.deposit(50)

Vous utilisez des objets depuis le début. En Python, les chaînes, les listes et même les fonctions sont des objets, c’est pourquoi vous pouvez écrire "hello".upper().

Votre premier cours

class Account:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.balance = balance

    def deposit(self, amount):
        if amount <= 0:
            raise ValueError("amount must be positive")
        self.balance += amount
        return self.balance

a = Account("Asha", 100)
b = Account("Ben")

a.deposit(50)
print(a.balance, b.balance)

# 150 0

__init__ s’exécute automatiquement chaque fois que vous créez un objet et définit l’état de départ. Le dépôt dans a n’a pas touché b, car chaque objet a ses propres données. Notez que la méthode protège également le solde d’une mauvaise valeur. Notre guide sur la gestion des exceptions Python explique raise plus en profondeur.

Qu’est-ce que le soi ?

self est simplement l’objet sur lequel une méthode travaille. Lorsque vous écrivez a.deposit(50), Python appelle effectivement Account.deposit(a, 50), en passant l’objet comme premier argument. C’est ainsi qu’une définition de méthode peut servir chaque objet.

Le nom self est une convention forte plutôt qu’un mot-clé, mais utilisez-le toujours. L’oublier dans une définition de méthode est l’erreur de débutant la plus courante et produit un message déroutant sur le nombre d’arguments.

Attributs de classe vs attributs d’instance

Un attribut défini directement dans le corps de la classe est partagé par tous les objets. Un ensemble sur self appartient uniquement à cet objet. Cet exemple montre comment se comportent les recherches :

class Account:
    interest_rate = 0.04    # class attribute

    def __init__(self, owner, balance=0):
        self.owner = owner  # instance attribute
        self.balance = balance

a = Account("Asha", 100)
b = Account("Ben")
print(a.interest_rate, b.interest_rate)   # 0.04 0.04

Account.interest_rate = 0.05
print(a.interest_rate, b.interest_rate)   # 0.05 0.05

a.interest_rate = 0.09
print(a.interest_rate, b.interest_rate, Account.interest_rate)
# 0.09 0.05 0.05

Cette dernière ligne surprend les gens. L’attribution via a n’a pas modifié la valeur partagée. Il a créé un nouvel attribut d’instance sur a qui masque celui de classe. Python regarde d’abord l’objet, puis la classe.

Méthodes spéciales (dunder)

Les méthodes avec des traits de soulignement doubles permettent à vos objets de fonctionner avec les fonctionnalités intégrées de Python. Sans eux, l’impression d’un compte affiche une adresse mémoire inutile. En ajouter deux lui donne une forme lisible :

    def __str__(self):
        return f"{self.owner}: {self.balance}"

    def __repr__(self):
        return f"Account({self.owner!r}, {self.balance})"

print(a)        # Asha: 150
print([a, b])   # [Account('Asha', 150), Account('Ben', 0)]
Méthode Déclenché par
__init__ Créer un objet
__str__ print(obj), str(obj)
__repr__ Débogage ou affichage dans une liste
__eq__ une == b
__len__ len(obj)
__add__ a + b

Héritage

L’héritage permet à une nouvelle classe de réutiliser une classe existante et de modifier uniquement ce qui diffère. Ici, Savings est un Account avec un paramètre supplémentaire :

class Savings(Account):
    def __init__(self, owner, balance=0, limit=3):
        super().__init__(owner, balance)
        self.limit = limit

    def __str__(self):
        return f"{super().__str__()} (savings)"

s = Savings("Chitra", 500)
s.deposit(100)
print(s, isinstance(s, Account), s.limit)

# Chitra: 600 (savings) True 3

super() appelle la version parent, donc la logique de configuration n’est pas répétée. deposit a été hérité tel quel et __str__ a été remplacé pour ajouter une étiquette. N’utilisez l’héritage que pour une véritable relation “est une”. Si une classe a simplement besoin de quelque chose, comme une voiture ayant besoin d’un moteur, donnez-lui cet objet comme attribut. C’est ce qu’on appelle la composition, et elle est généralement plus flexible que les chaînes d’héritage profondes.

Polymorphisme

Le polymorphisme signifie que différents objets peuvent répondre au même appel de méthode à leur manière. Le code appelant n’a pas besoin de connaître le type exact :

class Square:
    def __init__(self, side):
        self.side = side
    def area(self):
        return self.side ** 2

class Circle:
    def __init__(self, radius):
        self.radius = radius
    def area(self):
        return round(3.14159 * self.radius ** 2, 2)

for shape in [Square(3), Circle(2)]:
    print(type(shape).__name__, shape.area())

# Square 9
# Circle 12.57

Ces deux classes ne partagent même pas de parent. Python se soucie uniquement que l’objet ait une méthode area, une approche connue sous le nom de typage de canard. L’ajout d’un Triangle plus tard ne nécessiterait aucune modification de la boucle.

Encapsulation et propriétés

Python n’a pas d’attributs véritablement privés et s’appuie plutôt sur des conventions. Un simple trait de soulignement, comme dans _price, indique aux autres développeurs “ceci est interne, veuillez ne pas y toucher”. Pour vérifier les valeurs lorsqu’elles sont définies, utilisez une propriété, qui ressemble à un simple attribut vu de l’extérieur :

class Product:
    def __init__(self, price):
        self.price = price

    @property
    def price(self):
        return self._price

    @price.setter
    def price(self, value):
        if value < 0:
            raise ValueError("price cannot be negative")
        self._price = value

p = Product(100)
p.price = 150
print(p.price)      # 150
p.price = -5        # ValueError: price cannot be negative

Cela signifie que vous pouvez commencer avec un attribut simple et ajouter une validation ultérieurement sans modifier le code qui utilise la classe. N’écrivez donc pas les méthodes get_price() et set_price() par habitude, comme vous le feriez en Java. La syntaxe @ ici est un décorateur, que nous expliquons dans Explication des décorateurs Python.

Méthodes de classe et méthodes statiques

class Temperature:
    def __init__(self, celsius):
        self.celsius = celsius

    @classmethod
    def from_fahrenheit(cls, f):
        return cls(round((f - 32) * 5 / 9, 1))

    @staticmethod
    def is_freezing(celsius):
        return celsius <= 0

Temperature.from_fahrenheit(212).celsius   # 100.0
Temperature.is_freezing(-3)                # True
Tapez Premier argument Utilisez-le pour
Méthode d’instance soi Travailler avec les données d’un objet
@classmethod cls Constructeurs alternatifs
@staticmethod Aucun Aides liées à la classe

Classes de données

Lorsqu’une classe contient principalement des données, écrire __init__, __repr__ et __eq__ à la main est fastidieux. @dataclass les génère à partir d’annotations de type :

from dataclasses import dataclass, field

@dataclass
class Item:
    name: str
    price: int
    tags: list = field(default_factory=list)

print(Item("Pen", 10))
print(Item("Pen", 10) == Item("Pen", 10))

# Item(name='Pen', price=10, tags=[])
# True

Astuce : Tout n’a pas besoin d’un cours. Si elle n’a pas d’état et un seul comportement, une fonction simple est plus simple. Pour des recherches simples, un dictionnaire peut suffire. Recherchez une classe où les données et les règles qui les protègent vont clairement ensemble.

Erreurs courantes

Utiliser un attribut de classe mutable

C’est un bug classique. La liste est définie sur la classe, donc tous les paniers la partagent :

class Cart:
    items = []            # shared by every cart!

    def add(self, item):
        self.items.append(item)

c1, c2 = Cart(), Cart()
c1.add("pen")
print(c2.items)

# ['pen']

Créez-le dans __init__ avec self.items = [], afin que chaque objet obtienne sa propre liste.

Autres erreurs courantes

  • Oublier self. Écrivez self.balance, et non balance, dans les méthodes.
  • Oublier super().__init__(). L’enfant manque alors des attributs mis en place par le parent.
  • Créer d’énormes classes. Une classe qui fait tout est difficile à tester. Divisez-le par responsabilité.
  • Héritage profond. Deux niveaux suffisent généralement et la composition est souvent plus claire.
  • Ne pas écrire de tests. Les classes avec des règles sont faciles à tester, comme le montre notre tutoriel pytest à l’aide d’un petit chariot.

Pour conclure

Python orienté objet revient à regrouper les données avec le comportement qui les protège. Commencez par __init__, les méthodes et __str__, puis ajoutez l’héritage et les propriétés lorsque vous rencontrez un problème qu’ils résolvent. Comme étape suivante, prenez un script qui transmet les mêmes variables partout et transformez-les en une seule petite classe.

Questions fréquentes

Quelle est la différence entre une classe et un objet ?

Une classe est la définition ou le modèle. Un objet est une instance spécifique créée à partir de celui-ci, avec ses propres données. Une classe peut créer plusieurs objets.

Que fait __init__ en Python ?

C’est l’initialiseur, qui s’exécute automatiquement lorsque vous créez un objet. Il définit généralement les attributs de départ de l’objet à partir des arguments que vous transmettez.

Qu’est-ce que le soi en Python ?

self fait référence à l’objet sur lequel une méthode est appelée. Python le transmet automatiquement et permet à la méthode de lire et de modifier les attributs de cet objet.

Quels sont les quatre piliers de la POO ?

Ce sont l’encapsulation, l’abstraction, l’héritage et le polymorphisme. Ensemble, ils vous aident à regrouper les données avec le comportement, à masquer les détails et à réutiliser le code.

Quand dois-je utiliser une classe au lieu d’une fonction ?

Utilisez une classe lorsque les données et le comportement vont de pair dans plusieurs opérations. Pour une opération sans état, une fonction simple est plus simple et plus facile à tester.

Continuez à apprendre

Travailler avec Stack Quora

Besoin d’aide pour les tests, WordPress ou le référencement ?

Nous aidons les équipes à proposer de meilleurs logiciels et à développer leurs sites. Dites-nous sur quoi vous travaillez et nous vous proposerons une prochaine étape claire.

Continuez à lire

Plus de guides sur tests, IA et développement moderne

Vous avez apprécié cet article ? Choisissez un sujet et accédez directement à nos nouveaux didacticiels.

Intelligence artificielle

Les hallucinations de l'IA expliquées : pourquoi les modèles de langage inventent les choses et comment les réduire

Les hallucinations de l'IA ont expliqué : ce qu'elles sont, pourquoi les modèles de langage les produisent, les types courants, comment les réduire …

Lire l'article →
DevOps

Variables d'environnement expliquées : fichiers .env, secrets et configuration correctement effectués

Variables d'environnement expliquées avec des exemples Python que nous avons exécutés : lecture et définition, pourquoi chaque valeur est une chaîne…

Lire l'article →
Développement logiciel

Limitation du débit de l'API expliquée : algorithmes, en-têtes et gestion des erreurs 429

Limitation du débit de l'API expliquée avec une simulation que nous avons exécutée : compartiment de jetons, fenêtre fixe, fenêtre glissante, 429 ré…

Lire l'article →
Automatisation des tests

Se moquer en Python : unittest.mock, patch et les erreurs qui font mentir les tests

Moquerie en Python avec unittest.mock, testée : Mock et return_value, side_effect, correctifs où un nom est utilisé, spec et autospec, dates moqueus…

Lire l'article →
Tests logiciels

Couverture du code expliquée : couverture des lignes par rapport aux branches et ce que signifie réellement 100 %

Couverture du code expliquée avec une véritable exécution de cover.py : couverture des lignes, des branches et des conditions, lecture d'un rapport,…

Lire l'article →
Bases de données et SQL

DELETE vs TRUNCATE vs DROP dans SQL : différences, restauration et quand les utiliser

DELETE vs TRUNCATE vs DROP expliqué avec SQL testé : ce que chacun supprime, restauration, déclencheurs, réinitialisation d'identité, vitesse et en …

Lire l'article →
Bases de données et SQL

Vues SQL expliquées : créez, utilisez et évitez les pièges, avec des exemples

Vues SQL expliquées avec les requêtes que nous avons exécutées : création d'une vue, résultats en direct, masquage des colonnes, performances, vues …

Lire l'article →
Développement logiciel

Interface TypeScript vs Type : différences réelles, testées avec le compilateur

Interface TypeScript vs type, vérifiée avec le vrai compilateur : ce que les deux peuvent faire, ce qu'un seul peut faire, la fusion des déclaration…

Lire l'article →
Développement logiciel

Python *args et **kwargs expliqués : fonctions flexibles avec des exemples clairs

Python *args et **kwargs expliqués avec le code que nous avons exécuté : emballage et déballage, ordre des paramètres, arguments de mot-clé uniqueme…

Lire l'article →
Développement logiciel

Fonctions Python Lambda : syntaxe, utilisations réelles et quand ne pas les utiliser

Fonctions Python lambda expliquées avec le code que nous avons exécuté : syntaxe, tri avec clé, carte et filtre, fermetures, piège de liaison tardiv…

Lire l'article →
Intelligence artificielle

Que sont les agents IA ? Comment ils fonctionnent, avec une simple boucle d'agent que vous pouvez exécuter

Que sont les agents IA ? Un guide simple sur la boucle d'agent, les outils, la mémoire et les garde-fous, avec une petite boucle Python que nous avo…

Lire l'article →
DevOps

Surveillance vs observabilité : la vraie différence, avec les journaux, les métriques et les traces

Surveillance et observabilité expliquées : échecs connus et inconnus, journaux, métriques et traces, présentation pas à pas des incidents de paiemen…

Lire l'article →
DevOps

Volumes Docker vs montages Bind : conserver les données du conteneur de la bonne manière

Volumes Docker et montages de liaison expliqués : pourquoi les données du conteneur disparaissent, volumes nommés, montages de liaison, tmpfs, exemp…

Lire l'article →
Automatisation des tests

TDD vs BDD : principales différences, une fonctionnalité conçue dans les deux sens et quand les utiliser

TDD vs BDD expliqué avec une fonctionnalité de remise construite dans les deux sens : refactor rouge-vert avec le code que nous avons exécuté, scéna…

Lire l'article →
Tests logiciels

Tests d'acceptation utilisateur (UAT) : processus, liste de contrôle et exemples réels

Les tests d'acceptation des utilisateurs sont expliqués : qui les exécute, en quoi ils diffèrent du contrôle qualité, un processus en sept étapes, u…

Lire l'article →
Bases de données et SQL

Explication des valeurs SQL NULL : IS NULL, COALESCE, NULLIF et les pièges à éviter

Les valeurs SQL NULL expliquées avec les requêtes que nous avons exécutées : logique à trois valeurs, IS NULL, COALESCE, NULLIF, comment les agrégat…

Lire l'article →
Bases de données et SQL

Instruction SQL CASE WHEN : syntaxe, exemples réels et erreurs courantes

SQL CASE WHEN expliqué avec les requêtes que nous avons exécutées : formulaires simples et recherchés, ordre des conditions, pivots avec SUM, astuce…

Lire l'article →
Développement logiciel

Qu'est-ce que JWT ? Les jetons Web JSON expliqués avec un exemple fonctionnel

Qu’est-ce que JWT ? JSON Web Tokens expliqué : les trois parties, un jeton construit et falsifié dans le code que nous avons exécuté, JWT vs session…

Lire l'article →
Développement logiciel

Boucle d'événements JavaScript expliquée : pile d'appels, microtâches et minuteries avec des exemples

La boucle d'événements JavaScript expliquée avec le code que nous avons exécuté : pile d'appels, files d'attente de tâches et de microtâches, pourqu…

Lire l'article →
Développement logiciel

Générateurs Python et rendement expliqués : économisez de la mémoire avec des exemples réels

Les générateurs Python et le rendement expliqués avec le code que nous avons exécuté : comment ils s'arrêtent et reprennent, les économies de mémoir…

Lire l'article →
Intelligence artificielle

Que sont les intégrations ? Vecteurs et similarité cosinus expliqués simplement

Que sont les intégrations ? Un guide en langage simple sur les vecteurs, la similarité cosinus et la recherche sémantique, avec un petit exemple que…

Lire l'article →
DevOps

Déploiement Bleu-Vert vs Canary : différences, compromis et comment choisir

Explication du déploiement bleu-vert ou canari : comment chacun fonctionne, coût, risque et restauration, regroupement d'utilisateurs stable que nou…

Lire l'article →
Automatisation des tests

Tests instables : quelles sont leurs causes et comment les corriger définitivement

Des tests irréguliers expliqués avec des démos que nous avons exécutées : les principales causes, comment en confirmer et en diagnostiquer une, les …

Lire l'article →
Tests logiciels

Tests de charge vs tests de contrainte : différences, métriques et exemples k6

Explication des tests de charge et des tests de stress : ce que chacun prouve, les tests de pointe et de trempage, les métriques qui comptent, pourq…

Lire l'article →
Tests logiciels

Scénario de test et scénario de test : principales différences, exemples et quand les utiliser

Scénario de test et scénario de test expliqués : des définitions claires, un tableau côte à côte, une fonctionnalité de réinitialisation de mot de p…

Lire l'article →
Bases de données et SQL

Optimisation des requêtes SQL : lire les plans d'exécution et corriger les requêtes lentes, avec des délais

Optimisation des requêtes SQL testée sur un million de lignes : lire les plans d'exécution, ajouter les bons index, corriger les filtres non Sargabl…

Lire l'article →
Bases de données et SQL

SQL UNION vs UNION ALL : différences, exemples et performances testées

SQL UNION vs UNION ALL expliqué avec les requêtes que nous avons exécutées : des doublons, les règles suivent toutes les deux, un véritable bug de d…

Lire l'article →
Développement logiciel

Tutoriel API JavaScript Fetch : GET, POST, gestion des erreurs et délais d'attente

Un didacticiel de l'API JavaScript Fetch testé sur un serveur local : GET et POST, pourquoi 404 ne lance pas, un assistant réutilisable, des chaînes…

Lire l'article →
Développement logiciel

Gestion des fichiers Python : lecture, écriture, CSV, JSON et pathlib avec exemples

Gestion des fichiers Python expliquée avec le code que nous avons exécuté : modes ouverts, avec lecture de fichiers volumineux, CSV, JSON, pathlib, …

Lire l'article →
Développement logiciel

Classes et objets Python : didacticiel POO avec des exemples réels

Classes et objets Python expliqués avec le code que nous avons exécuté : __init__, méthodes, attributs de classe par rapport à l'instance, héritage,…

Lire l'article →
Intelligence artificielle

Qu'est-ce qu'un grand modèle de langage ? Comment fonctionnent les LLM, expliqués sans battage médiatique

Qu’est-ce qu’un grand modèle de langage ? Les LLM expliqués en langage simple : jetons, intégrations, attention, formation, fenêtres de température …

Lire l'article →
DevOps

Commandes Linux pour les débutants : le guide du terminal essentiel avec des exemples

Commandes Linux pour débutants, regroupées par tâche : navigation, fichiers, affichage des journaux, grep, tuyaux, autorisations, processus et archi…

Lire l'article →
Automatisation des tests

Selenium vs Playwright : principales différences, code comparé et lequel choisir

Comparatif Selenium vs Playwright : architecture, attente, support du navigateur et du langage, débogage, même test dans les deux outils, conseils d…

Lire l'article →
Tests logiciels

Partitionnement d'équivalence : technique de conception de tests expliquée avec des exemples concrets

Le partitionnement d'équivalence expliqué : comment trouver des partitions valides et invalides, des exemples concrets d'âges, de mots de passe et d…

Lire l'article →
Tests logiciels

Gravité vs priorité dans les tests logiciels : différences, matrice et exemples réels

Explication de la gravité et de la priorité dans les tests logiciels : des définitions claires, une matrice à quatre voies avec des exemples, des éc…

Lire l'article →
Bases de données et SQL

Tutoriel sur les sous-requêtes SQL : types, sous-requêtes corrélées et EXISTE avec des exemples

Un didacticiel sur les sous-requêtes SQL avec les requêtes que nous avons exécutées : les sous-requêtes scalaires, IN, FROM et SELECT, les sous-requ…

Lire l'article →
Bases de données et SQL

Transactions SQL et ACID expliquées : COMMIT, ROLLBACK et niveaux d'isolement

Transactions SQL et ACID expliquées avec un virement bancaire que nous avons effectué : COMMIT, ROLLBACK, points de sauvegarde, verrous, niveaux d'i…

Lire l'article →
Développement logiciel

Git merge vs rebase : différences, exemples et quand utiliser chacun

Git merge vs rebase expliqué avec de vraies sorties de log, un tableau comparatif, la règle d'or du rebase et un flux de travail sûr pour les équipes.

Lire l'article →
Développement logiciel

List comprehension Python : syntaxe, exemples et cas à éviter

La list comprehension Python expliquée : syntaxe, filtres, if-else, boucles imbriquées, temps mesurés et cas où une boucle for classique est préféra…

Lire l'article →
Bases de données et SQL

Jointures SQL expliquées avec exemples (Inner, Left, Right, Full)

Comprenez les jointures SQL pas à pas avec des tables et requêtes d'exemple : INNER, LEFT, RIGHT, FULL, CROSS et SELF, plus erreurs courantes et con…

Lire l'article →