Vocabulaire de la programmation objet

Objectifs :

  • Écrire la définition d’une classe.
  • Accéder aux attributs et méthodes d’une classe.

Les classes font partie d'un paradigme (méthode) de programmation appelé programmation orientée objet (POO). La programmation orientée objet essaie de simuler la réalité à l'aide d'objets. Elle se concentre sur la création de types d'objets réutilisables appelés classes.
Lorsque l'on souhaite utiliser une classe dans un programme, on crée alors un objet à partir de cette classe, d'où l'expression « orienté objet ».

1. Types natifs Python (c'est-à-dire intégrés à Python)

In [ ]:
nbre = 1.7
In [ ]:
type(nbre)
In [ ]:
verite = True
In [ ]:
type(verite)
In [ ]:
# Une cgaîne de caractères
ma_chaine = "abracadabra"
In [ ]:
type(ma_chaine)
In [ ]:
ma_chaine.upper()
In [ ]:
# Une nouvelle liste
ma_liste = [1, 3]
In [ ]:
type(ma_liste)
In [ ]:
ma_liste.append(5)
In [ ]:
ma_liste
In [ ]:
ma_liste.insert(1, "a")
In [ ]:
ma_liste
In [ ]:
# Un nouveau tuple
mon_tuple = ("a", "b", "c", "a")
In [ ]:
type(mon_tuple)
In [ ]:
mon_tuple.count("a")
In [ ]:
# Un nouveau dictionnaire
mon_dico = {'one': 1, 'two': 2, 'three': 3}
In [ ]:
type(mon_dico)
In [ ]:
cles = list(mon_dico.keys())
In [ ]:
print(cles)

etc.
Les objets (mon_string, ma_liste, mon_tuple, mon_dico) sont des exemples de chacune de leur classe.
Ces objets créés héritent des propriétés (attributs) et des comportements (méthodes) propres à la classe à laquelle ils sont issues.
Par exemple, on peut mesurer la longueur d'une séquence (str, tuple, list) à l'aide de la fonction len(), insérer un objet dans une liste à l'aide la méthode append(), récupérer les clés d'un dictionnaire grâce à la méthode keys()...

2. Types définis par l'utilisateur

Un type défini par l'utilisateur est également appelé une classe.

In [ ]:
class Point:
    """
        Représente un point dans le plan
    """
    pass

L'objet classe est comme une usine de création d'objets. Pour créer un point, on appelle Point comme s'il s'agissait d'une fonction.

In [ ]:
#Créer le point A
A = Point()
In [ ]:
print(A)

La procédure print() n'est pas encore définie pour notre nouvelle classe Point !
La valeur de retour est une référence à un objet Point (dont l'adresse mémoire est 0x000001ABEA09E6A0), que nous identifions grâce à la variable A.
La création d'un nouvel objet s'appelle instanciation, et l'objet créé est une instance de la classe.

In [ ]:
B = Point()
In [ ]:
print(B)

2.1. Attributs de classe - attributs d'instance

Python est un langage de programmation orienté objet, ce qui signifie qu'il fournit des fonctionnalités qui prennent en charge la programmation orientée objet.

Créons une classe Personne

In [ ]:
class Personne:
    """
        Représente une personne qui fréquente le lycée.
    """
    # C'est l'usine à fabriquer des personnes qui fréquentent le lycée
    pass
In [ ]:
#Un autre exemple
class Fusee:
    """
    Modélise une fusée dans un jeu
    ou une simulation en physique.
    """
    pass

2.1.1. Attributs d'instance : La méthode __init__

Les propriétés que tous les objets (personnes) issus de la classe (l'usine Personne) doivent avoir sont définies dans une méthode spéciale (méthode dunder) appelée __init__ (deux caractères de soulignement, suivis de init, puis de deux autres traits de soulignement).
Chaque fois qu'un nouvel objet personne est instancié (est créé), __init__() définit l'état initial de l'objet en attribuant les valeurs des propriétés de l'objet. Autrement dit, il initialise chaque nouvelle instance de la classe.

In [ ]:
class Personne:
    """
        Représente une personne qui fréquente le lycée ;
        chacune ayant un prénom, un nom et un âge.
    """
    ecole = "Saint Pierre Institut"         #Attribut (variable) de classe
        
    def __init__(self, prenom, nom, age):
        print("Une nouvelle personne vient d'intégrer le lycée !")
        self.prenom = prenom
        self.nom = nom
        self.age = age

Les attributs créés dans __init__() sont appelés attributs d'instance (des données locales). La valeur d'un attribut d'instance est spécifique à une instance particulière (personne) de la classe Personne : tous les objets (personnes) ont un prénom, un nom et un âge mais, les valeurs des attributs prenom, nom et age sont propres à chaque personne.

2.1.2. Attributs de classe

Les attributs de classe sont des attributs qui ont la même valeur pour toutes les instances de classe. On peut définir un attribut de classe en affectant une valeur à un nom de variable en dehors de la méthode __init__().
Par exemple, toutes les personnes (toutes les instances) créées sont de Saint Pierre Institut (attribut de classe).

In [ ]:
#Créer une instance (un élève) 
personne1 = Personne("Moïse", "Dupond", 16)
In [ ]:
#L'objet personne1 est-il une instance de Personne ?
isinstance(personne1, Personne)
In [ ]:
personne2 = Personne("Ben", "Achraf", 15)
In [ ]:
#L'objet personne2 est-il une instance de la classe Personne ?
isinstance(personne2, Personne)
In [ ]:
#Les instances personne1 et personne2 sont-elles les mêmes ?
personne1 == personne2
In [ ]:
#attribut d'instance
personne1.nom
In [ ]:
#attribut d'instance
personne2.age
In [ ]:
#attribut de classe
personne1.ecole
In [ ]:
#attribut de classe
personne2.ecole
In [ ]:
#Le même attribut de classe
Personne.ecole
In [ ]:
#Un autre exemple
class Fusee:
    """
    Modélise une fusée dans un jeu
    ou une simulation en physique.
    Chaque fusée est initialement à la position x= 0 et y=0
    """
    def  __init__ (self, x=0, y=0): 
        print("Une fusée vient d'être créée !")
        self.x = x
        self.y = y
In [ ]:
# Créez une instance de Fusée
ma_fusee = Fusee(1, 25)
In [ ]:
print(ma_fusee)

Modifier des attributs

L'un des principaux avantages de l'utilisation de classes pour organiser les données est que les instances sont garanties d'avoir les attributs que l'on attend. Ainsi, toutes les instances ont des attributs prénom, nom et age.
Toutefois, bien que l'existence des attributs soit garantie, leurs valeurs peuvent être modifiées dynamiquement par l'utilisateur final !

In [ ]:
#On modifie l'âge de personne1
personne1.age = 18
In [ ]:
personne1.age
In [ ]:
#On modifie l'attribut de classe
personne1.ecole = "Lycée Descartes"
In [ ]:
del personne1.nom
In [ ]:
personne1.nom

Espace de noms

In [ ]:
#espace de noms
vars(Personne)
In [ ]:
#espace de noms
vars(personne1)
In [ ]:
personne1.__dict__
In [ ]:
#espace de noms
vars(personne2)
In [ ]:
personne2.__dict__

2.2. Méthodes (comportements) d'instance

2.2.1. Définition

Les méthodes d'instance sont des fonctions définies à l'intérieur d'une classe et ne peuvent être appelées qu'à partir d'une instance de cette classe. Tout comme __init__(), le premier paramètre d'une méthode d'instance est toujours self. L'appel d'une méthode se fait à l'aide de la notation pointée.

In [ ]:
class Personne:
     """
        Représente une personne qui fréquente le lycée ;
        chacune ayant un prénom, un nom et un âge.
    """
    ecole = "Lycée Saint Pierre" #variable de classe
    
    def __init__(self, prenom, nom, age):
        assert isinstance(age, int)
        assert isinstance(prenom, str)
        assert isinstance(nom, str)
        self.prenom = prenom
        self.nom = nom
        self.age = age
        
    # Une méthode d'instance
    def presentation(self):
        return f"{self.prenom} {self.nom} agé(e) de {self.age} ans."
In [ ]:
Margot = Personne("Margot", "Yacine", 15)
In [ ]:
print(Margot) 
In [ ]:
Margot.presentation()
In [ ]:
#Un autre exemple
class Fusee:
    """
    Modélise une fusée dans un jeu
    """
    def  __init__ (self, x = 0, y = 0): 
        assert isinstance(x, (int, float)) and isinstance(y, int|float)
        #x et y sont soit des int soit des float
        self.x = x 
        self.y = y
    def  mettre_en_mouvement(self, pas_horizontal = 0, pas_vertical = 1):
        # Incrémentez la position y de la fusée.
        self.x += pas_horizontal
        self.y += pas_vertical
In [ ]:
# Créer un objet Fusee et commencer à le faire monter.
ma_fusee = Fusee()
print(f"Altitude de la fusée : {ma_fusee.y}")

ma_fusee.mettre_en_mouvement()
print(f"Altitude de la fusée : {ma_fusee.y}")

ma_fusee.mettre_en_mouvement()
print(f"Altitude de la fusée : {ma_fusee.y}")

Exercice :

  • Créer, en compréhension, une flotte de 5 fusées et les stocker dans une liste ma_flotte.
  • Montrer que chaque fusée est un objet séparé (par leur adresse mémoire).
  • Faire monter la première fusée.
  • Déplacer la troisième fusée à la position (7, 15).
  • Afficher les coordonnées de chaque fusée.
In [ ]:
 

2.2.2. Les méthodes __str__ et __repr__

__str__ ( __repr__ ) est une méthode spéciale, comme __init__, qui est censée renvoyer une représentation sous forme de chaîne de caractères d'un objet.
Autrement dit, lorsque l'on utilise l'instruction print() sur un objet, il invoque la méthode str (repr).

In [ ]:
repr("a")
In [ ]:
repr(1)
In [ ]:
str("a")
In [ ]:
str(1)
In [ ]:
class Personne:
     """
        Représente une personne qui fréquente le lycée ;
        chacune ayant un prénom, un nom et un âge.
    """
    ecole = "Lycée Saint Pierre" #variable de classe
    
    def __init__(self, prenom, nom, age):
        self.prenom = prenom
        self.nom = nom
        self.age = age
        
    # méthode d'instance
    def __str__(self):
        return f"{self.prenom} {self.nom} agé(e) de {self.age} ans."
In [ ]:
Margot = Personne("Margot", "Yacine", 15)
In [ ]:
print(Margot)
In [ ]:
Margot
In [ ]:
class Personne:
    """
        Représente une personne qui fréquente le lycée ;
        chacune ayant un prénom, un nom et un âge.
    """
    ecole = "Lycée Saint Pierre" #attribut (variable) de classe
    
    def __init__(self, prenom, nom, age):
        self.prenom = prenom
        self.nom = nom
        self.age = age
    
      # méthode d'instance
    def __str__(self):
        return f"{self.prenom} {self.nom} agé(e) de {self.age} ans."
    
    # méthode d'instance
    def __repr__(self) -> str:
        return f"{type(self).__name__}(prénom = {self.prenom}, nom = {self.nom}, âge = {self.age})"
In [ ]:
Margot = Personne("Margot", "Aïssatou", 15)
In [ ]:
Margot

2.2.3. Autres méthodes

In [ ]:
class Personne:
    """
        Représente une personne qui fréquente le lycée ;
        chacune ayant un prénom, un nom et un âge.
    """
    ecole = "Lycée Saint Pierre"     #variable de classe
    
    def __init__(self, prenom, nom, age):
        self.prenom = prenom
        self.nom = nom
        self.age = age
        self.nom_prenom = self.nom + self.prenom
        
    # méthode d'instance
    def __str__(self):
        return f"{self.prenom} {self.nom} agé(e) de {self.age} ans."
    
    # Une méthode d'instance
    def __repr__(self) -> str:
        return f"{type(self).__name__}(prénom = {self.prenom}, nom = {self.nom}, âge = {self.age})"
    
    #Une autre méthode d'instance
    def __len__(self):
        """
        Renvoie le nombre de lettres contenues dans nom_prenom.
        """
        return len(self.nom_prenom)
    
    #Encore une autre méthode
    def __contains__(self, lettre):
        """
            Renvoie True si lettre est dans self.nom_prenom, False dans le cas contraire.
        """
        return lettre in self.nom_prenom
In [ ]:
Margot = Personne("Margot", "Yacine", 15)
In [ ]:
len(Margot)
In [ ]:
"e" in Margot
In [ ]:
#Un autre exemple
class Fusee:
    """
    Modélise une fusée dans un jeu
    """
    def  __init__ (self, x = 0, y = 0): 
        # Chaque fusée a une position (x ; y)
        assert isinstance(x, (int, float)) and isinstance(y, (int, float))#x et y sont soit des int soit des float
        self.x = x 
        self.y = y
        
    def  mettre_en_mouvement(self, pas_horizontal = 0, pas_vertical = 1):
        # Incrémentez la position y de la fusée.
        self.x += pas_horizontal
        self.y += pas_vertical   
In [ ]:
# Créer un objet Fusee et commencer à le faire monter, comme suit.
ma_fusee = Fusee()
print(f"Altitude de la fusée : {ma_fusee._y}")

ma_fusee.mettre_en_mouvement()
print(f"Altitude de la fusée : {ma_fusee._y}")

ma_fusee.mettre_en_mouvement()
print(f"Altitude de la fusée : {ma_fusee._y}")
    Exercice :
  • Ajouter une nouvelle méthode, get_distance, qui renvoie la distance entre une fusée auto-référencée et une autre.
  • Créer l'instance, fusee2, qui a pour abscisse x = 3 et y = 10.
  • Déterminer la distance entre ma_fusee et fusee2
In [ ]:
 

2.3. Encapsulation

2.3.1. Définition

L'un des rôles principaux d'une classe est d'encapsuler (de cacher, d'envelopper) les données et les détails d'implémentation internes d'un objet. L'objectif étant de protéger les objets de la classe des usagers qui seraient tentés de modifier directectement leur état.
La conséquence : les objets ne sont accessibles qu'au travers de leur interface c'est-à-dire via leurs attributs et méthodes.

En Python, par défaut, les attributs sont publics, donc modifiables par l'utilisateur final. Mais quelquefois, on ne souhaite pas que l'usager altère certains attributs d'une instance :

  • en préfixant son nom d'un caractères de soulignement bas.
In [ ]:
class Personne:
     """
        Représente une personne qui fréquente le lycée ;
        chacune ayant un prénom, un nom et un âge.
    """
    ecole = "Saint Pierre Institut"         #Attribut (variable) de classe
        
    def __init__(self, prenom, nom, age):
        print("Une nouvelle personne vient d'intégrer le lycée !")
        self._prenom = prenom
        self._nom = nom
        self._age = age
In [ ]:
#Créer une instance (un élève) 
personne1 = Personne("Dupond", 16)
In [ ]:
personne1._nom
In [ ]:
 

le tiret bas ( _ ) qui préfixe une variable permet simplement de signaler aux autres programmeurs que ladite variable est à usage interne ; mais elle demeure accessible et modifiable.

In [ ]:
personne1._nom
  • en préfixant son nom de deux caractères de soulignement bas : le name mangling
In [ ]:
class Personne:
    """
        Représente une personne qui fréquente le lycée ;
        chacune ayant un prénom, un nom et un âge.
    """
    ecole = "Saint Pierre Institut"         #Attribut (variable) de classe
        
    def __init__(self, prenom, nom, age):
        print("Une nouvelle personne vient d'intégrer le lycée !")
        self__prenom = prenom
        self.__nom = nom
        self.__age = age
In [ ]:
#Créer une instance (un élève) 
personne1 = Personne("Dupond", "Anaïs", 16)
In [ ]:
personne1.__nom
In [ ]:
dir(personne1)

Malgré le double tiret bas ( _ ) qui préfixe une variable, elle reste toujours accessible de l'extérieur. Mais le code est un peu plus complexe que précedemment.

In [ ]:
personne1._Personne__nom

2.3.1. Contrôle de l'accès : attributs gérés

En Python, il est conseillé d'être aussi explicite que possible. L'usage d'un décorateur (@property) permet de mieux contrôler l'accès aux attributs et méthodes.

In [ ]:
#Ici, tous les attributs sont accessibles en lecture, écriture et suppression
class Personne:
    """
        Représente une personne qui fréquente le lycée ;
        chacune ayant un prénom, un nom et un âge.
    """
    ecole = "Saint Pierre Institut"         #Attribut (variable) de classe
        
    def __init__(self, prenom, nom, age):
        print("Une nouvelle personne vient d'intégrer le lycée !")
        self._prenom = prenom
        self._nom = nom
        self._age = age
        
    @property
    def prenom(self):
        """Récupère le prénom de l'instance (personne.)"""
        return self._prenom

    @prenom.setter
    def prenom(self, nouveau_nom):
        """Modifie le prénom de l'instance."""
        self._prenom = nouveau_nom

    @prenom.deleter
    def prenom(self):
        """Supprime le prénom de l'instance."""
        del self._prenom

    @property
    def nom(self):
        """Récupère le nom de l'instance (personne.)"""
        return self._nom

    @nom.setter
    def nom(self, nouveau_nom):
        """Modifie le nom de l'instance."""
        self._nom = nouveau_nom

    @nom.deleter
    def nom(self):
        """Supprime le nom de l'instance."""
        del self._nom

    @property
    def age(self):
        """Obtient l'âge de l'instance."""
        return self._age

    @age.setter
    def age(self, nouvel_age):
        """Change l'âge de l'intance."""
        self._age = nouvel_age

    @age.deleter
    def age(self):
        """Supprime l'âge de l'instance"""
        del self._age

      # méthode d'instance
    def __str__(self):
        return f"{self.prenom} {self.nom} agé(e) de {self.age} ans."

    # Une méthode d'instance
    def __repr__(self) -> str:
        return f"{type(self).__name__}(prénom = {self.prenom}, nom = {self.nom}, âge = {self.age})"
In [ ]:
#Créer une instance (un élève) 
personne1 = Personne("Mathieu", "Dupond", 16)
In [ ]:
personne1.nom
In [ ]:
personne1.age
In [ ]:
#espace de nom
vars(personne1)

Limiter l'accès : fournir des attributs en lecture seule

In [ ]:
#Ici, les attributs ne sont accessibles qu'en lecture
#C'est simplement une information pour les programmeurs !
class Personne:
    """
        Représente une personne qui fréquente le lycée ;
        chacune ayant un prénom, un nom et un âge.
    """
    ecole = "Saint Pierre Institut"         #Attribut (variable) de classe
        
    def __init__(self, prenom, nom, age):
        print("Une nouvelle personne vient d'intégrer le lycée !")
        self._nom = nom
        self._prenom = prenom
        self._age = age
        
        @property
        def prenom(self):
            """Récupère le prénom de l'instance (personne.)"""
            return self._prenom
       
        @property
        def nom(self):
            """Obtient le nom de l'instance (personne.)"""
            return self._nom
        
        @property
        def age(self):
            """Obtient l'âge de l'instance."""
            return self._age  
        
        # méthode d'instance
        def __str__(self):
            return f"{self.prenom} {self.nom} agé(e) de {self.age} ans."

        # Une méthode d'instance
        def __repr__(self) -> str:
            return f"{type(self).__name__}(prénom = {self.prenom}, nom = {self.nom}, âge = {self.age})"
In [ ]:
 
In [ ]:
#Créer une instance (un élève) 
personne1 = Personne("Mathieu", "Dupond", 16)
In [ ]:
personne1._nom
In [ ]:
personne1._nom = 'rose'
In [ ]:
personne1._nom

2.5. Héritage

Une classe permet de créer des objets (instances). La classe et ses objets sont liés par une relation d'héritage. Autrement dit, les objets reçoivent tous les attributs et méthodes définis dans la classe.
Par ailleurs, l'héritage permet de créer un sous-ensemble d'une classe. Ainsi, il permet d'étendre une classe, notamment par

  • l'ajout de nouvelles méthodes
  • la redéfinition de certaines des méthodes existantes
  • l'ajout de nouveaux attributs aux instances
In [ ]:
#Ici, tous les attributs sont accessibles en lecture, écriture et suppression
class Personne:
    """
        Représente une personne qui fréquente le lycée ;
        chacune ayant un prénom, un nom et un âge.
    """
    ecole = "Saint Pierre Institut"         #Attribut (variable) de classe
        
    def __init__(self, prenom, nom, age):
        print("Une nouvelle personne vient d'intégrer le lycée !")
        self._prenom = prenom
        self._nom = nom
        self._age = age
        
        @property
        def prenom(self):
            """Récupère le prénom de l'instance (personne.)"""
            return self._prenom
        
        @prenom.setter
        def prenom(self, nouveau_nom):
            """Modifie le prénom de l'instance."""
            self._prenom = nouveau_nom
        
        @prenom.deleter
        def prenom(self):
            """Supprime le prénom de l'instance."""
            del self._prenom
         
        @property
        def nom(self):
            """Récupère le nom de l'instance (personne.)"""
            return self._nom
        
        @nom.setter
        def nom(self, nouveau_nom):
            """Modifie le nom de l'instance."""
            self._nom = nouveau_nom
        
        @nom.deleter
        def nom(self):
            """Supprime le nom de l'instance."""
            del self._nom
        
        @property
        def age(self):
            """Obtient l'âge de l'instance."""
            return self._age
        
        @age.setter
        def age(self, nouvel_age):
            """Change l'âge de l'intance."""
            self._age = nouvel_age
        
        @age.deleter
        def age(self):
            """Supprime l'âge de l'instance"""
            del self._age  
            
        # méthode d'instance
        def __str__(self):
            return f"{self.prenom} {self.nom} agé(e) de {self.age} ans."

        # Une méthode d'instance
        def __repr__(self) -> str:
            return f"{type(self).__name__}(prénom = {self.prenom}, nom = {self.nom}, âge = {self.age})"
In [ ]:
class Eleve(Personne):
    def __init__(self, prenom, nom, age, niveau):
        super().__init__(prenom, nom, age)#On charrie l'initialisation de la classe parent
        self.niveau = niveau  
In [ ]:
eleve1 = Eleve("Claude", "Adam", 16, "première")
In [ ]:
isinstance(eleve1, Eleve)
In [ ]:
isinstance(eleve1, Personne)
In [ ]:
eleve1._prenom
In [ ]:
eleve1.ecole
In [ ]:
print(eleve1)
In [ ]:
#Un autre exemple
class Fusee:
    """
    Modélise une fusée dans un jeu
    """
    def  __init__ (self, x = 0, y = 0): 
        # Chaque fusée a une position (x ; y)
        assert isinstance(x, (int, float)) and isinstance(y, (int, float))#x et y sont soit des int soit des float
        self._x = x 
        self._y = y
    
    #Attributs en lecture seule
    @property
    def x(self):
        """Récupère la position x de la fusée."""
        return self._x
        
    @property
    def y(self):
        """Récupère la position y de la fusée."""
        return self._y
    
    def  mettre_en_mouvement(self, pas_horizontal = 0, pas_vertical = 1):
        # Incrémentez la position y de la fusée.
        self._x += pas_horizontal
        self._y += pas_vertical
    
    def get_distance(self, une_autre_fusee):
        import math
        """Renvoie la distance de cette fusée à une_autre_fusee."""
       
    
    def __str__(self):
        return f"Je me trouve à l'altitude {self._y} et horizontalement à {self._x} de mon point de départ."
    
    # Une méthode d'instance
    def __repr__(self) -> str:
        return f"{type(self).__name__}(x = {self.x}, y = {self.y})"
In [ ]:
#un autre exemple
class Navette(Fusee):
    """Modélise une navette spatiale (fusée réutilisable).""" 
    def __init__(self, x=0, y=0, nbre_vols=0):
        super().__init__(x, y)
        self.nbre_vols = nbre_vols
        
    def __str__(self):
        return f"Je suis une navette spatiale et me trouve à l'altitude {self._y} et horizontalement à {self._x} de mon point de départ."
    
    # Une méthode d'instance
    def __repr__(self) -> str:
        return f"{type(self).__name__}(x = {self.x}, y = {self.y})"
In [ ]:
navette = Navette(10, 0, 3)
print(navette)
In [ ]:
isinstance(navette, Navette)
In [ ]:
isinstance(navette, Fusee)

2.6. Polymorphisme

Le polymorphisme est la propriété de pouvoir traiter différents types d'objets de la même manière et de faire en sorte que chacun de ces objets réagisse à sa manière.
En POO, le polymorphisme signifie qu'une même méthode appliquée à des objets de classes différentes liées par une relation d'héritage permet d'obtenir des résultats différents mais appropriés.
Les méthodes str et repr, par exemple, sont attachées aussi bien attachées aux objet Fusee qu'aux objets Navette.

2.7. Modules et classes

Plus le fichier contenant les classes se densifient plus il devient difficile de le manipuler. Aussi est-il conseillé d'enregistrer les classes dans un fichier à part, sous forme de module puis de les importer quand on en a besoin.
On peux enregistrer une ou plusieurs classes dans un fichier.
Exemple :
Enregistrer la classe Personne dans un fichier nommé personne.py.

In [ ]:
#Dans un nouveau fichier contenu dans le même répertoire que personne.py
from personne import Personne
une_personne = Personne("Ben", "Yacine", 25)
print(une_personne)

Exercice :

  • À partir de la classe personne, ci-après, créer la classe Professeur où chaque professeur enseigne une matière.
In [ ]:
#Ici, tous les attributs sont accessibles en lecture, écriture et suppression
class Personne:
    """
        Représente une personne qui fréquente le lycée ;
        chacune ayant un prénom, un nom et un âge.
    """
    ecole = "Saint Pierre Institut"         #Attribut (variable) de classe
        
    def __init__(self, prenom, nom, age):
        print("Une nouvelle personne vient d'intégrer le lycée !")
        self._prenom = prenom
        self._nom = nom
        self._age = age
        
        @property
        def prenom(self):
            """Récupère le prénom de l'instance (personne.)"""
            return self._prenom
        
        @prenom.setter
        def prenom(self, nouveau_nom):
            """Modifie le prénom de l'instance."""
            self._prenom = nouveau_nom
        
        @prenom.deleter
        def prenom(self):
            """Supprime le prénom de l'instance."""
            del self._prenom
         
        @property
        def nom(self):
            """Récupère le nom de l'instance (personne.)"""
            return self._nom
        
        @nom.setter
        def nom(self, nouveau_nom):
            """Modifie le nom de l'instance."""
            self._nom = nouveau_nom
        
        @nom.deleter
        def nom(self):
            """Supprime le nom de l'instance."""
            del self._nom
        
        @property
        def age(self):
            """Obtient l'âge de l'instance."""
            return self._age
        
        @age.setter
        def age(self, nouvel_age):
            """Change l'âge de l'intance."""
            self._age = nouvel_age
        
        @age.deleter
        def age(self):
            """Supprime l'âge de l'instance"""
            del self._age  
            
            # méthode d'instance
    def __str__(self):
        return f"{self._prenom} {self._nom} agé(e) de {self._age} ans."
    
    # Une méthode d'instance
    def __repr__(self):
        return f"Personne({self._prenom}, {self._nom}, {self._age})"
  • On considère, ci-après, les classes Fusee et Navette.
In [ ]:
#Un autre exemple
class Fusee:
    """
    Modélise une fusée dans un jeu
    """
    def  __init__ (self, x = 0, y = 0): 
        # Chaque fusée a une position (x ; y)
        assert isinstance(x, (int, float)) and isinstance(y, (int, float))#x et y sont soit des int soit des float
        self.x = x 
        self.y = y
    
    def  mettre_en_mouvement(self, pas_horizontal = 0, pas_vertical = 1):
        # Incrémentez la position y de la fusée.
        self.x += pas_horizontal
        self.y += pas_vertical
    
    def get_distance(self, une_autre_fusee):
        import math
        """Renvoie la distance de cette fusée à une_autre_fusee."""
        
    
    def __str__(self):
        return f"Je me trouve à l'altitude {self.y} et horizontalement à {self.x} de mon point de départ."
    
    def __repr__(self):
        return f"Fusee({self.x}, {self.y})"
In [ ]:
#un autre exemple
class Navette(Fusee):
    """Modélise une navette spatiale (fusée réutilisable).""" 
    def __init__(self, x=0, y=0, nbre_vols=0):
        super().__init__(x, y)
        self.nbre_vols = nbre_vols
        
    def __str__(self):
        return f"Je suis une navette spatiale et me trouve à l'altitude {self._y} et horizontalement à {self._x} de mon point de départ."
    
    # Une méthode d'instance
    def __repr__(self) -> str:
        return f"{type(self).__name__}(x = {self.x}, y = {self.y})"

On donne également le code suivant :

In [ ]:
from random import randint
navettes = []
for x in range(3):
    x = randint(0, 100)
    y = randint(1, 100)
    nbre_vols = randint(0, 10)
    navettes.append(Navette(x, y, nbre_vols))
    
ma_flotte = []
for x in range(3):
    x = randint(0, 100)
    y = randint(1, 100)
    ma_flotte.append(Fusee(x, y))
  1. Afficher le nombre de vols effectués par chaque navette spatiale. On affichera : navette n°1 suivi du nombre de vols.
  2. Afficher la distance de la première navette à toutes les autres.
  3. Afficher la distance de la première navette à toutes les fusées.
In [ ]: