Quelques fonctions intégrées
all(iterable)
Renvoie True si tous les éléments de l'itérable sont vrais :
                            
                            all([True, True, False])  # False
                            
                            
                            content_copy
                        any(iterable)
Renvoie True si au moins un élément de l'itérable est vrai :
                            
                            any([True, False, False])  # True
                            
                            
                            content_copy
                        count
                            
                            nombres = [1, 2, 2, 2, 4, 5]
                            print(nombres.count(2)) # 3
                            
                            
                            content_copy
                        enumerate(iterable, start=0)
Renvoie un itérateur qui donne des tuples contenant l'index et la valeur de chaque élément de l'itérable :
                            
                            list(enumerate(['a', 'b', 'c']))  
                            # [(0, 'a'), (1, 'b'), (2, 'c')]
                            
                            
                            content_copy
                        filter(function, iterable)
Construit un itérateur à partir des éléments de l'itérable pour lesquels la fonction est vraie :
                            
                            list(filter(lambda x: x > 0, [-1, 0, 1, 2]))  # [1, 2]
                            
                            
                            content_copy
                        index
Utilisation de la méthode index() pour trouver l'indice de la première occurrence d'un élément.
                            
                            nombres = [1, 2, 3, 2]
                            print(nombres.index(2))     # 1                           
                            
                            
                            content_copy
                        isinstance(object, classinfo)
Vérifie si un objet est une instance ou une sous-classe de classinfo :
                            
                            isinstance(5, int)  # True
                            
                            
                            content_copy
                        map(function, iterable)
Applique une fonction à tous les éléments d'un itérable :
                            
                            list(map(str, [1, 2, 3]))  
                            # ['1', '2', '3']
                            
                            
                            content_copy
                        Utilisation de lambda
Utilisation d'une fonction lambda pour doubler les nombres de la liste :
                            
                            nombres = [1, 2, 3, 4]
                            tmp = map(lambda x: x * 2, nombres)
                            nombres2 = list(tmp)
                            print(nombres2)    # [2, 4, 6, 8]
                            
                            
                            content_copy
                        max(iterable, *[, key, default])
Renvoie le plus grand élément d'un itérable :
                            
                            max([1, 2, 3])  # 3
                            
                            
                            content_copy
                        min(iterable, *[, key, default])
Renvoie le plus petit élément d'un itérable :
                            
                            min([1, 2, 3])  # 1
                            
                            
                            content_copy
                        range(start, stop[, step])
Génère une séquence de nombres :
                            
                            list(range(1, 10, 2))  # [1, 3, 5, 7, 9]
                            
                            
                            content_copy
                        sorted
Renvoie une nouvelle liste triée des éléments dans l'itérable :
                            
                            # sorted(iterable, *, key=None, reverse=False)
                            sorted([3, 1, 2])  # [1, 2, 3]
                            
                            
                            content_copy
                        zip(*iterables)
Agrège des éléments provenant de plusieurs itérables :
                            
                            list(zip([1, 2, 3], ['a', 'b', 'c']))  
                            # [(1, 'a'), (2, 'b'), (3, 'c')]
                            
                            
                            content_copy
                        Chaînes de caractères
strip
Supprime les espaces (ou les caractères spécifiés) en début et en fin de chaîne :
                            
                            " hello ".strip()  # 'hello'
                            
                            
                            content_copy
                        split(sep=None, maxsplit=-1)
Divise la chaîne en une liste :
                            
                            "a,b,c".split(',')  # ['a', 'b', 'c']
                            
                            
                            content_copy
                        join(iterable)
Concatène les éléments de l'itérable avec la chaîne comme séparateur :
                            
                            ','.join(['a', 'b', 'c'])  # 'a,b,c'
                            
                            
                            content_copy
                        find(sub[, start[, end]])
Renvoie l'index de la première occurrence de sub :
                            
                            "hello".find('e')  # 1
                            
                            
                            content_copy
                        Types de variables
En Python, il n'y a pas de typage explicite. Par conséquent, une variable détermine son type en fonction de la valeur qui lui est assignée.
                        
                        # Entier (int)
                        x = 10
                        # Flottants (float)
                        y = 3.14
                        # Chaînes de caractères (str)
                        message = "Bonjour à tous."
                        
                        
                    Les dictionnaires
Les dictionnaires en Python sont des structures de données très utiles qui permettent de stocker des paires clé-valeur.
Créer un dictionnaire
Méthode 1: Utilisation des accolades {}
                            
                            mon_dictionnaire = {
                                "prenom": "Mahmoud",
                                "age": 25,
                                "etudiant": True
                            }   
                            
                            
                            content_copy
                        Méthode 2: Utilisation de la fonction dict()
                            
                            mon_dictionnaire = dict(nom="Mahmoud", age=25, etudiant=True)  
                            
                            
                            content_copy
                        Accéder aux Éléments
Par clé
                            
                            prenom = mon_dictionnaire["nom"]
                            print(prenom) # Mahmoud 
                            
                            
                            content_copy
                        avec la méthode get()
                            
                            age = mon_dictionnaire.get("age")
                            print(age)  # 25
                            
                            
                            content_copy
                        Utiliser une valeur par défaut si la clé n'existe pas
                            
                            nom = dico.get("ILLOURMANE", "Inconnue")
                            print(nom)  # Inconnue
                            
                            
                            content_copy
                        Modifier un Dictionnaire
Ajouter ou mettre à jour un élément
                            
                            mon_dictionnaire["profession"] = "Développeur"
                            mon_dictionnaire["age"] = 26                            
                            
                            
                            content_copy
                        Supprimer un élément
Utilisation de del :
                            
                            del mon_dictionnaire["etudiant"]                                                 
                            
                            
                            content_copy
                        Utilisation de pop :
                            
                            profession = mon_dictionnaire.pop("profession")
                            print(profession)  # Développeur                                                                  
                            
                            
                            content_copy
                        
                            Utilisation de popitem :
                            
                            Supprime et renvoie la paire clé-valeur
                        
                            
                            dernier_element = mon_dictionnaire.popitem()
                            print(dernier_element)    # ('cle', valeur)                                                                                     
                            
                            
                            content_copy
                        Parcours
Clés uniquement
                            
                            for clé in mon_dictionnaire.keys():
                                print(clé)                                                                             
                            
                            
                            content_copy
                        Valeurs uniquement
                            
                            for valeur in mon_dictionnaire.values():
                                print(valeur)                                                                   
                            
                            
                            content_copy
                        Paires clé-valeur
                            
                            for clé, valeur in mon_dictionnaire.items():
                                print(clé, valeur)                                                                           
                            
                            
                            content_copy
                        Vérifier la présence d'une clé
                            
                            if "nom" in mon_dictionnaire:
                                print("La clé 'nom' est présente.")                                                                             
                            
                            
                            content_copy
                        Longueur du dictionnaire
                            
                            print(len(mon_dictionnaire))
                            
                            
                            content_copy
                        Vider le dictionnaire
                            
                            mon_dictionnaire.clear()
                            print(mon_dictionnaire)  # {}                                
                            
                            
                            content_copy
                        Copier un dictionnaire
                            
                            # Shallow copy
                            copie_dictionnaire = mon_dictionnaire.copy()
                            
                            # Deep copy
                            import copy
                            copie_profonde_dictionnaire = copy.deepcopy(mon_dictionnaire)                                                                
                            
                            
                            content_copy
                        Dictionnaires Imbriqués
                            
                            etudiants = {
                                "etudiant1": {"nom": "Mahmoud", "age": 25},
                                "etudiant2": {"nom": "Bob", "age": 23},
                            }
                            
                            print(etudiants["etudiant1"]["nom"])  # Mahmoud                                                                                              
                            
                            
                            content_copy
                        Compréhension de dictionnaire
                            
                            cubes = {x: x**3 for x in range(5)}
                            print(cubes)  
                            # {0: 0, 1: 1, 2: 8, 3: 27, 4: 64}                                                                                                                            
                            
                            
                            content_copy
                        Utilisation de defaultdict
defaultdict est une sous-classe de dictionnaire qui appelle une fonction pour fournir une valeur par défaut pour une clé inexistante. Cela évite les erreurs lorsqu'on tente d'accéder à une clé qui n'existe pas encore dans le dictionnaire.
                            
                            from collections import defaultdict
                            # Dictionnaire initial
                            dico = {
                                "nom": "Mahmoud",
                                "age": 25,
                                "etudiant": True
                            }
                            # Création d'un defaultdict avec str comme fonction par défaut
                            default_dico = defaultdict(str, dico)
                            # Accès à une clé existante
                            print(default_dico["nom"])  # Mahmoud
                            # Accès à une clé inexistante
                            print(default_dico["profession"])  # Sortie : une chaîne vide
                            # Affichage du dictionnaire complet
                            print(default_dico)  
                            # defaultdict(<class 'str'>, {'nom': 'Mahmoud', 
                            # 'age': 25, 'etudiant': True, 'profession': 'Développeur'})
                            
                            
                            content_copy
                        Utilisation de orderedDict
OrderedDict est une sous-classe de dictionnaire qui se souvient de l'ordre dans lequel les éléments ont été ajoutés.
                            
                            from collections import OrderedDict
                            dictionnaire_ordre = OrderedDict()
                            dictionnaire_ordre["cle1"] = 1
                            dictionnaire_ordre["cle2"] = 2
                            dictionnaire_ordre["cle3"] = 3
                            
                            print(dictionnaire_ordre)  
                            # OrderedDict([('cle1', 1), ('cle2', 2), ('cle3', 3)])
                            
                            
                            content_copy
                        Les ensembles
Les ensembles sont une collection non ordonnée d'éléments uniques et immuables. Ils sont très utiles pour les opérations de test d'appartenance, la suppression de doublons et les opérations mathématiques telles que l'union, l'intersection, etc.
Création d'une ensemble
                            
                            # Utilisation de la fonction set()
                            ensemble_vide = set()
                            
                            # Création d'un ensemble avec des éléments
                            ensemble = {1, 2, 3, 4, 5}
                            
                            
                        Conversion d'une liste en ensemble
                            
                            liste = [1, 2, 2, 3, 4]
                            ensemble_from_liste = set(liste)  # {1, 2, 3, 4}
                            
                            print(ensemble_vide)         # Output: set()
                            print(ensemble)              # Output: {1, 2, 3, 4, 5}
                            print(ensemble_from_liste)   # Output: {1, 2, 3, 4}
                            
                            
                        Ajout et suppression d'éléments
Ajouter un élément
                            
                            ensemble = {1, 2, 3}
                            ensemble.add(4)
                            print(ensemble)  # Output: {1, 2, 3, 4}
                            
                            
                        Ajouter plusieurs éléments
                            
                            ensemble.update([5, 6])
                            print(ensemble)  # Output: {1, 2, 3, 4, 5, 6}
                            
                            
                        Supprimer un élément
                            
                            ensemble.remove(3)
                            print(ensemble)  # Output: {1, 2, 4, 5, 6}                                
                            
                            
                        Supprimer un élément de manière sécurisée
                            
                            ensemble.discard(10)  # Ne fait rien si l'élément n'est pas présent
                            print(ensemble)       # Output: {1, 2, 4, 5, 6}                              
                            
                            
                        Supprimer un élément aléatoiree
                            
                            element = ensemble.pop()
                            print(element)  # Un élément aléatoire
                            print(ensemble) # Ensemble sans l'élément aléatoire retiré                          
                            
                            
                        Vider un ensemble
                            
                            ensemble.clear()
                            print(ensemble)  # Output: set()                         
                            
                            
                        Opérations sur les ensembles
Union
L'union de deux ensembles contient tous les éléments des deux ensembles.
                            
                            ensemble1 = {1, 2, 3}
                            ensemble2 = {3, 4, 5}
                            
                            union = ensemble1 | ensemble2
                            print(union)  # Output: {1, 2, 3, 4, 5}
                            
                            # Utilisation de la méthode union()
                            union = ensemble1.union(ensemble2)
                            print(union)  # Output: {1, 2, 3, 4, 5}
                            
                            
                        List
Les listes sont un type de données qui permet de stocker une collection ordonnée d'éléments.
Création d'une list
Création traditionnelle :
                            
                            nombres = [1, 2, 3, 4, 5]
                            
                            
                        Comprehension
On peut créer des list en utilisant le style de programmation par comprehension pour créer des listes en appliquant une expression à chaque élément d'une autre séquence :
                            
                            nombres = [1, 2, 3, 4, 5]
                            # Créer une liste avec le carré de chaque nombre
                            carres = [x**2 for x in nombres]
                            print(carres)  # Sortie: [1, 4, 9, 16, 25]
                            
                            
                        Ajouter des éléments à une liste
La méthode append() ajoute un élément à la fin de la liste.
                                        
                                        nombres = [1, 2, 3, 4, 5]
                                        nombres.append(6)
                                        print(nombres)  # Sortie: [1, 2, 3, 4, 5]
                                        
                                        
                                    La méthode insert() permet d'insérer un élément à une position spécifique dans la liste.
                                        
                                        nombres = [1, 2, 3, 4]
                                        nombres.insert(4, 5)
                                        print(nombres)  # Sortie: [1, 2, 3, 4, 5]
                                        
                                        
                                    Étendre une liste
                            
                            nombres = [1, 2]
                            nombres.extend([3, 4])  # [1, 2, 3, 4]                                
                            
                            
                        Supprimer des éléments d'une liste
Le mot-clé del permet de supprimer un élément ou une tranche d'une liste.
                                        
                                        nombres = [1, 2, 3, 4, 5]
                                        del nombres[4]
                                        print(nombres)  # Sortie: [1, 2, 3, 4]
                                        
                                        
                                    La méthode remove() permet de supprimer la première occurrence d'une valeur spécifiée.
                                        
                                        nombres = [1, 2, 3, 4, 5, 2]
                                        nombres.remove(2)
                                        print(nombres)  # Sortie: [1, 3, 4, 5, 2]
                                        
                                        
                                    Retirer un élément d'une liste
Retire et renvoie l'élément à la position i :
                            
                            nombres = [1, 2, 3]
                            nombres.pop(0) # [2, 3] 
                            # Si aucun paramètre retire le dernier élément                                
                            
                            
                        Inverser les éléments
                            
                            nombres = [1, 2, 3]
                            nombres.reverse()  # [3, 2, 1]                                                                
                            
                            
                        Trier une liste
La méthode sort() trie la liste sur place.
                                        
                                        nombres = [3, 1, 4, 1, 5, 9, 2]
                                        nombres.sort()
                                        print(nombres)  # Sortie: [1, 1, 2, 3, 4, 5, 9]
                                        
                                        
                                    La fonction sorted() renvoie une nouvelle liste triée sans modifier l'originale.
                                        
                                        nombres = [3, 1, 4, 1, 5, 9, 2]
                                        nombres_triee = sorted(nombres)
                                        print(nombres_triee)  # Sortie: [1, 1, 2, 3, 4, 5, 9]
                                        
                                        
                                    Copier une liste
Copie superficielle :
                                        
                                        nombres = [3, 1, 4, 1, 5, 9, 2]
                                        copie = nombres.copy()
                                        
                                        
                                    Copie en profondeur (pour les listes imbriquées ou les objets mutables)
                                        
                                        import copy
                                        nombres = [[1, 2], [3, 4]]
                                        copie = copy.deepcopy(nombres)
                                        
                                        
                                    Parcours list
                                        
                                        nombres = [1, 2, 3, 4, 5]
                                        for nombre in nombres:
                                            print(nombre)
                                        
                                        
                                    On peut parcourir une liste en utilisant des indices si on a besoin d'accéder à la fois à l'élément et à son index.
                                        
                                            nombres = [1, 2, 3, 4, 5]
                                            for i in range(len(nombres)):
                                                print(f"Index {i}: {nombres[i]}")
                                        
                                        
                                    La fonction enumerate() permet de parcourir une liste tout en récupérant à la fois l'indice et l'élément.
                                        
                                        ma_liste = [1, 2, 3, 4, 5]
                                        for i, element in enumerate(ma_liste):
                                            print(f"Index {i}: {element}")
                                        
                                        
                                    Convertir un tuple en liste
                            
                            t = (1, 2, 3)
                            l = list(t)
                            print(l)  # Sortie: [1, 2, 3]                                                                                             
                            
                            
                        Tuple
                        Les tuples sont similaires aux listes, mais ils sont immuables, 
                        ce qui signifie qu'une fois créés, leurs éléments ne peuvent
                        pas être modifiés.
                        
                        TypeError: 'tuple' object does not support item assignment
                    
Création de Tuples
On peut créer des tuples soit en utilisant des () ou en n'utilisant rien du tout :
                            
                            t1 = (1, 2, 3)
                            t2 = 1, 2, 3
                            t3 = ()     # tuple vide
                            t4 = (42,)  # virgule obligatoire
                            
                            
                        Tuples Imbriqués
On peut créer des tuples contenant d'autres tuples :
                            
                            t = ((1, 2), (3, 4))
                            print(t[0])  # Sortie: (1, 2)
                            print(t[1][1])  # Sortie: 4                                
                            
                            
                        Accès aux Éléments
On utilise les indices pour accéder aux éléments.
                            
                            print(t1[0])    # 1
                            print(t1[-1])   # 3
                            print(t2[0])    # 1
                            print(t3)       # ()
                            print(t4[0])    # 42
                            
                            
                        Découpage (slicing)
On peut utiliser des tranches pour accéder à une sous-partie du tuple.
                            
                            t = (1, 2, 3, 4, 5)
                            print(t[1:3])  # Sortie: (2, 3)
                            print(t[:3])  # Sortie: (1, 2, 3)
                            print(t[3:])  # Sortie: (4, 5)
                            print(t[:])  # Sortie: (1, 2, 3, 4, 5)                                
                            
                            
                        Concaténation
                                
                                t1 = (1, 2)
                                t2 = (3, 4)
                                print(t1 + t2)  # Sortie: (1, 2, 3, 4)
                                
                                
                            Répétition
                                
                                t = (1, 2)
                                print(t * 3)  # Sortie: (1, 2, 1, 2, 1, 2)                                    
                                
                                
                            Appartenance
                                
                                t = (1, 2, 3)
                                print(2 in t)  # Sortie: True
                                print(4 in t)  # Sortie: False                                    
                                
                                
                            Assigner les valeurs d'un tuple (Unpacking)
                                
                                mon_tuple = (1, 'deux', 3.0)
                                a, b, c = mon_tuple
                                print(a)  # Sortie: 1
                                print(b)  # Sortie: 'deux'
                                print(c)  # Sortie: 3.0                                                                       
                                
                                
                            Opérateur * pour déballer une partie du tuple :
                                
                                t = (1, 2, 3, 4, 5)
                                a, *b, c = t
                                print(a)  # Sortie: 1
                                print(b)  # Sortie: [2, 3, 4]
                                print(c)  # Sortie: 5                                                                                                          
                                
                                
                            Utilisation des Tuples comme Clés de Dictionnaire
                                
                                # Création d'un dictionnaire avec des tuples comme clés
                                dictionnaire = {
                                    (1, 2): 'a',
                                    (3, 4): 'b'
                                }
                                
                                print(dictionnaire[(1, 2)])  # Sortie: 'a'
                                print(dictionnaire[(3, 4)])  # Sortie: 'b'                                                            
                                
                                
                            Fonctions Renvoyant des Tuples
                                
                                def division_et_reste(dividende, diviseur):
                                quotient = dividende // diviseur
                                reste = dividende % diviseur
                                return quotient, reste
                                
                                q, r = division_et_reste(10, 3)
                                print(q)  # Sortie: 3
                                print(r)  # Sortie: 1
                                
                                
                            Convertir une liste en tuple
                                
                                l = [1, 2, 3]
                                t = tuple(l)
                                print(t)  # (1, 2, 3)                                    
                                
                                
                            Les classes
Convention de nommage
En Python, il n'y a pas de mots-clés natifs pour déclarer explicitement des attributs comme publics, privés ou protégés comme dans certains autres langages de programmation comme Java. Cependant, il existe des conventions et des pratiques de codage pour indiquer l'intention derrière l'accès aux attributs dans une classe.
- Public : En Python, tous les attributs et méthodes sont publics par défaut, ce qui signifie qu'ils peuvent être accédés et modifiés depuis n'importe où en dehors de la classe.
- Protégé _ : Par convention, un attribut ou une méthode est considéré comme protégé lorsqu'il est préfixé par un seul trait de soulignement ( _ ). Cela signifie qu'il est généralement destiné à être utilisé à l'intérieur de la classe elle-même ou par ses sous-classes, mais il peut encore être accédé depuis l'extérieur de la classe.
- Privé __ : Par convention, un attribut ou une méthode est considéré comme privé lorsqu'il est préfixé par deux traits de soulignement ( __ ). Cela signifie qu'il est destiné à être utilisé uniquement à l'intérieur de la classe elle-même, et les tentatives d'accès direct depuis l'extérieur de la classe lèveront généralement une erreur d'attribut.
Définition d'une classe
Une classe en Python est une structure qui permet de regrouper des données et des fonctions sous une même entité, facilitant ainsi la création et la manipulation d'objets ayant des caractéristiques et des comportements similaires.
                            
                            class Personne:
                                nom_commun = "Humain" # Attribut de classe
                                def __init__(self, nom, age):
                                    self.nom = nom  # Attribut de l'instance
                                    self.age = age  # Attribut de l'instance
                                
                                def __del__(self):
                                    print("Objet détruit.")
                                # Méthode de l'instance
                                def saluer(self):
                                    return f"Bonjour, je m'appelle {self.nom} et j'ai {self.age} ans."  
                                
                                # Méthode de classe
                                @classmethod
                                def saluer_commune(cls):  
                                    return f"Bonjour, {cls.nom_commun}!"
                                # Méthode statique
                                @staticmethod
                                def saluer_statique():
                                    return f"Bonjour, tout le monde!"
                            # Création d'une instance de la classe Personne
                            personne = Personne("Mahmoud", 25)
                            # Appel de la méthode d'instance sur l'instance
                            print(personne.saluer())  # Bonjour, Mahmoud!
                            
                            # Appel de la méthode de classe sur la classe
                            print(Personne.saluer_commune())  # Bonjour, Humain!
                            # Appel de la méthode statique de la classe
                            print(Personne.saluer_statique())  # Bonjour, tout le monde
                            
                            
                            content_copy
                        Définition d'une classe
Les classes peuvent hériter des attributs et des méthodes d'autres classes.
                            
                            class Personne:
                                def __init__(self, nom, age):
                                    self.nom = nom
                                    self.age = age
                            
                                def afficher_informations(self):
                                    print(f"Nom: {self.nom}, Age: {self.age}")
                            
                            class Employe(Personne):
                                def __init__(self, nom, age, employe_id, poste):
                                    # Appel du constructeur de la classe parente
                                    super().__init__(nom, age)
                                    # Ajout d'attributs spécifiques à la classe dérivée
                                    self.employe_id = employe_id
                                    self.poste = poste
                            
                                def afficher_informations(self):
                                    # Appel de la méthode afficher_informations de la classe parente
                                    super().afficher_informations()
                                    # Ajout d'informations spécifiques à l'employé
                                    print(f"ID Employé: {self.employe_id}, Poste: {self.poste}")
                            
                            # Instanciation d'un objet de la classe dérivée
                            employe = Employe("Mahmoud", 25, "J98", "Développeur")
                            
                            # Appel de la méthode afficher_informations
                            employe.afficher_informations()
                            
                            
                            content_copy
                        Surcharge de méthodes
Les méthodes peuvent être redéfinies dans une classe dérivée pour modifier leur comportement.
                            
                            class MaClasse:
                                def methode1(self):
                                    print("Méthode1 originale appelée.")
                                
                                def methode2(self):
                                    print("Méthode2 originale appelée.")
                            
                            class ClasseDerivee(MaClasse):
                                def methode1(self):
                                    print("Méthode1 surchargée appelée.")
                                    # Appel de la méthode de la classe parente
                                    super().methode1()
                            
                            # Instanciation d'un objet de la classe dérivée
                            mon_objet = ClasseDerivee()
                            
                            # Appel de la méthode1
                            mon_objet.methode1()  # Affiche "Méthode1 surchargée appelée." suivi de "Méthode1 originale appelée."
                            
                            # Appel de la méthode2 originale
                            MaClasse.methode2(mon_objet)   #Affiche "Méthode2 originale appelée."
                            
                            
                            content_copy
                        Polymorphisme
Le polymorphisme permet à des objets de différentes classes d'être traités de manière uniforme s'ils partagent une interface commune.
                            
                            class Animal:
                                def parler(self):
                                    pass
                            
                            class Chien(Animal):
                                def parler(self):
                                    return "Woof!"
                            
                            class Chat(Animal):
                                def parler(self):
                                    return "Meow!"
                            
                            # Fonction utilisant le polymorphisme
                            def faire_parler(animal):
                                return animal.parler()
                            
                            # Instanciation d'objets
                            mon_chien = Chien()
                            mon_chat = Chat()
                            
                            # Appel de la fonction avec différents objets
                            print(faire_parler(mon_chien))  # Affiche "Woof!"
                            print(faire_parler(mon_chat))   # Affiche "Meow!"                            
                            
                            
                            content_copy
                        Classe Abstraite
L'abstraction en programmation orientée objet permet de créer des modèles généraux pour des fonctionnalités, sans se préoccuper des détails spécifiques d'implémentation. Par exemple, une classe abstraite peut définir une méthode sans en fournir le code exact. Les classes qui en héritent doivent alors fournir leur propre implémentation de cette méthode, en fonction de leurs besoins particuliers. Cela assure que chaque type d'objet a la même interface pour une fonctionnalité donnée, mais permet à chaque classe d'implémenter cette fonctionnalité de manière unique, en fonction de ses caractéristiques spécifiques.
                            
                            from abc import ABC, abstractmethod
                            class Vehicule(ABC):
                                @abstractmethod
                                def deplacer(self):
                                    pass
                            
                            class Voiture(Vehicule):
                                def deplacer(self):
                                    return "Je me déplace sur quatre roues."
                            
                            class Avion(Vehicule):
                                def deplacer(self):
                                    return "Je vole dans les airs."
                            
                            # Instanciation d'objets et appel de la méthode abstraite
                            ma_voiture = Voiture()
                            mon_avion = Avion()
                            
                            print(ma_voiture.deplacer())   # Affiche "Je me déplace sur quatre roues."
                            print(mon_avion.deplacer())    # Affiche "Je vole dans les airs."                   
                            
                            
                            content_copy
                        Les Environnements Virtuels
Généralités
Les environnements virtuels sont des outils essentiels pour le développement Python. Ils permettent d'isoler les projets et les dépendances les uns des autres, ce qui prévient les conflits et facilite la gestion des paquets.
Qu'est-ce qu'un environnement virtuel Python ?
Un environnement virtuel Python est un espace isolé dans lequel vous pouvez installer des paquets spécifiques pour un projet particulier. Il s'agit d'un répertoire contenant sa propre copie de l'interpréteur Python, de la bibliothèque standard et des paquets installés.
Créer un environnement virtuel
                            Python 3 dispose d'un module intégré appelé venv pour créer et gérer des environnements virtuels.
                            
                            Dans le répertoire actuel, la commande suivante va créer un environnement virtuel appelé
                            mon_env :
                        
                            
                            python3 -m venv mon_env
                            
                            
                            content_copy
                        Utilisation
                            Après avoir créé notre environnement virtuel, on peut maintenant créer un répertoire à la 
                            racine de notre environnement virtuel et y mettre notre projet Python que l'on souhaite développer.
                            
                            Par exemple :
                        
                            
                            mon_env/
                            ├── mon_projet_flask/
                            │   ├── __init__.py
                            │   ├── app.py
                            │   ├── templates/
                            │   │   └── index.html
                            │   └── static/
                            │       └── style.css
                            ├── bin|Scripts sous Windows
                            ├── include
                            ├── lib
                            ├── lib64|Pas sur Windows
                            ├── pyvenv.cfg
                            └── requirements.txt
                            
                            
                        Activer l'environnement virtuel
Pour activer un environnement virtuel, nous devons exécuter un script d'activation. Le nom du script dépend de notre système d'exploitation :
Sous Windows
                            
                            M:\mon_env> .\Scripts\activate
                            (mon_env) M:\mon_env>
                            
                            
                        Sous Max/Linux
                            
                            mahmoud@vm:~/mon_env$ source bin/activate
                            (mon_env) mahmoud@xen:~/mon_env$
                            
                            
                        Désactiver un environnement virtuel
Pour désactiver un environnement virtuel :
                            
                            deactivate
                            
                            
                            content_copy
                        Installer des paquets dans un environnement virtuel
Une fois l'environnement virtuel activé, vous pouvez installer des paquets à l'aide de la commande pip comme d'habitude :
                            
                            pip install requests
                            
                            
                        Gérer les paquets dans un environnement virtuel
On peut utiliser les commandes pip habituelles pour gérer les paquets dans un environnement virtuel :
- pip list : Affiche la liste des paquets installés
- pip install nom_du_paquet : Installe un paquet
- pip uninstall nom_du_paquet : Désinstalle un paquet
- pip freeze > requirements.txt : Exporte la liste des paquets installés dans un fichier requirements.txt
Supprimer un environnement virtuel
Pour supprimer un environnement virtuel, on supprime simplement le répertoire correspondant.