├── Cours_1_Introduction_Python ├── Correction_exercices.ipynb ├── Cours_1_Introduction.ipynb ├── Séance 1 - Les bases de la programmation.pdf └── zen.py ├── Cours_2_Fonctions_et_modules ├── Séance_2_Fonctions_et_modules_corrections.ipynb ├── Séance 2 - Fonctions et modules.pdf └── Séance_2_Fonctions_et_modules.ipynb ├── Cours_3_Introduction_POO ├── Seance_3_Exercices.ipynb ├── Séance 3 - Programmation orientée objet 1.pdf └── Séance_3_Base_Programmation_Orientée_Objet.ipynb ├── Cours_4_POO_2 ├── Exercices_Séance_4.ipynb ├── Exercices_Séance_4_correction.ipynb ├── Séance_4_Introduction à la Programmation Orientée Objet(2).ipynb └── Séance 4 - Programmation orientée objet 2.pdf ├── Cours_5_IIIF_Manipulations_données ├── Cours_5_Utilisation de l’API IIIF et manipulation de données 1.ipynb └── Séance 5 - Introduction à IIIF et à la manipulation de fichiers.pdf ├── Cours_6_Utilisation_IIIF_manipulation_données_2 ├── Cours_6_IIIF_manipulations_2.ipynb ├── Exercice_guide.ipynb └── Séance 6 - Introduction à IIIF et à la manipulation de fichiers 2.pdf └── Evaluation ├── Correction_evaluation.ipynb └── Evaluation_python_20241104.pdf /Cours_1_Introduction_Python/Correction_exercices.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# **Solutions des exercices**" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## **Exercice 1 : Manipulation des types de données de base**" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": null, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "nombre = 10 # int\n", 24 | "pi = 3.14159 # float\n", 25 | "message = \"Ceci est une chaîne de caractères\" # str\n", 26 | "est_utile = True # bool\n", 27 | "\n", 28 | "print(nombre, type(nombre))\n", 29 | "print(pi, type(pi))\n", 30 | "print(message, type(message))\n", 31 | "print(est_utile, type(est_utile))" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": {}, 37 | "source": [ 38 | "## **Exercice 2 : Manipulation des listes**" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": null, 44 | "metadata": {}, 45 | "outputs": [], 46 | "source": [ 47 | "films = [\"Inception\", \"Le Seigneur des Anneaux\", \"Matrix\", \"Interstellar\", \"Blade Runner\"]\n", 48 | "print(films[2]) # Troisième film\n", 49 | "\n", 50 | "films.append(\"Fight Club\") # Ajouter un nouveau film\n", 51 | "films.sort() # Trier la liste\n", 52 | "\n", 53 | "print(films)" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": {}, 59 | "source": [ 60 | "## **Exercice 3 : Utilisation des tuples**" 61 | ] 62 | }, 63 | { 64 | "cell_type": "code", 65 | "execution_count": null, 66 | "metadata": {}, 67 | "outputs": [], 68 | "source": [ 69 | "jours = (\"Lundi\", \"Mardi\", \"Mercredi\", \"Jeudi\", \"Vendredi\", \"Samedi\", \"Dimanche\")\n", 70 | "print(jours)\n", 71 | "\n", 72 | "# Essayer de modifier un élément\n", 73 | "# jours[0] = \"Sunday\" # Cela provoquera une erreur : TypeError" 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": {}, 79 | "source": [ 80 | "## **Exercice 4 : Manipulation des dictionnaires**" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": null, 86 | "metadata": {}, 87 | "outputs": [], 88 | "source": [ 89 | "livre = {\"titre\": \"1984\", \"auteur\": \"George Orwell\", \"année\": 1949}\n", 90 | "print(livre[\"titre\"])\n", 91 | "\n", 92 | "livre[\"pages\"] = 328\n", 93 | "print(livre)" 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": {}, 99 | "source": [ 100 | "## **Exercice 5 : Manipulation de chaînes de caractères**" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": null, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [ 109 | "phrase = input(\"Entrez une phrase : \")\n", 110 | "mots = phrase.split(\" \")\n", 111 | "print(\"Nombre de mots :\", len(mots))\n", 112 | "print(\"Phrase en majuscules :\", phrase.upper())" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "## **Exercice 6 : Vérification d'un nombre pair ou impair**\n" 120 | ] 121 | }, 122 | { 123 | "cell_type": "code", 124 | "execution_count": null, 125 | "metadata": {}, 126 | "outputs": [], 127 | "source": [ 128 | "nombre = int(input(\"Entrez un nombre entier : \"))\n", 129 | "if nombre % 2 == 0:\n", 130 | " print(\"Le nombre est pair.\")\n", 131 | "else:\n", 132 | " print(\"Le nombre est impair.\")" 133 | ] 134 | }, 135 | { 136 | "cell_type": "markdown", 137 | "metadata": {}, 138 | "source": [ 139 | "## **Exercice 7 : Calcul de la somme des nombres pairs de 1 à 100**" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": null, 145 | "metadata": {}, 146 | "outputs": [], 147 | "source": [ 148 | "somme = 0\n", 149 | "for i in range(1, 101):\n", 150 | " if i % 2 == 0:\n", 151 | " somme += i\n", 152 | "print(\"La somme des nombres pairs de 1 à 100 est :\", somme)" 153 | ] 154 | }, 155 | { 156 | "cell_type": "markdown", 157 | "metadata": {}, 158 | "source": [ 159 | "#### **Exercice 8 : Jeu de devinette**" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": null, 165 | "metadata": {}, 166 | "outputs": [], 167 | "source": [ 168 | "import random\n", 169 | "\n", 170 | "nombre_secret = random.randint(1, 10)\n", 171 | "essai = None\n", 172 | "\n", 173 | "while essai != nombre_secret:\n", 174 | " essai = int(input(\"Devinez le nombre entre 1 et 10 : \"))\n", 175 | " if essai < nombre_secret:\n", 176 | " print(\"Trop petit !\")\n", 177 | " elif essai > nombre_secret:\n", 178 | " print(\"Trop grand !\")\n", 179 | " else:\n", 180 | " print(\"Bravo, vous avez trouvé le nombre secret :\", nombre_secret)" 181 | ] 182 | } 183 | ], 184 | "metadata": { 185 | "language_info": { 186 | "name": "python" 187 | } 188 | }, 189 | "nbformat": 4, 190 | "nbformat_minor": 2 191 | } 192 | -------------------------------------------------------------------------------- /Cours_1_Introduction_Python/Séance 1 - Les bases de la programmation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaouabti/Cours_ENC_Introduction_programmation_Python/7dce58e731a47ba702bba33e292090c8b1e7612d/Cours_1_Introduction_Python/Séance 1 - Les bases de la programmation.pdf -------------------------------------------------------------------------------- /Cours_1_Introduction_Python/zen.py: -------------------------------------------------------------------------------- 1 | import this -------------------------------------------------------------------------------- /Cours_2_Fonctions_et_modules/Séance_2_Fonctions_et_modules_corrections.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Corrections des exercices" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## **Exercice 1 :**\n", 15 | "\n", 16 | "Écrivez un programme qui demande à l'utilisateur d'entrer un nombre et qui indique si ce nombre est positif, négatif ou nul.\n", 17 | "\n", 18 | "*Hint* : utilisez la fontion input()" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 5, 24 | "metadata": {}, 25 | "outputs": [ 26 | { 27 | "name": "stdout", 28 | "output_type": "stream", 29 | "text": [ 30 | "Le nombre est positif.\n" 31 | ] 32 | } 33 | ], 34 | "source": [ 35 | "# Réponse\n", 36 | "nombre = float(input(\"Entrez un nombre : \"))\n", 37 | "\n", 38 | "if nombre > 0:\n", 39 | " print(\"Le nombre est positif.\")\n", 40 | "elif nombre < 0:\n", 41 | " print(\"Le nombre est négatif.\")\n", 42 | "else:\n", 43 | " print(\"Le nombre est nul.\")" 44 | ] 45 | }, 46 | { 47 | "cell_type": "markdown", 48 | "metadata": {}, 49 | "source": [ 50 | "## **Exercice 2 :**\n", 51 | "\n", 52 | "Écrivez un programme qui affiche les nombres pairs de 0 à 20." 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "for i in range(0, 21, 2):\n", 60 | " print(i)" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "## **Exercice 3 :**\n", 68 | "\n", 69 | "Écrivez un programme qui demande à l'utilisateur de deviner un nombre secret entre 1 et 10.\n", 70 | "\n", 71 | "*Hint* : utiliser random.randint(1, 10)" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": 6, 77 | "metadata": {}, 78 | "outputs": [ 79 | { 80 | "name": "stdout", 81 | "output_type": "stream", 82 | "text": [ 83 | "C'est plus grand.\n", 84 | "C'est plus grand.\n", 85 | "Bravo ! Vous avez trouvé le nombre secret.\n" 86 | ] 87 | } 88 | ], 89 | "source": [ 90 | "import random\n", 91 | "\n", 92 | "nombre_secret = random.randint(1, 10)\n", 93 | "devine = False\n", 94 | "\n", 95 | "while not devine:\n", 96 | " essai = int(input(\"Devinez le nombre entre 1 et 10 : \"))\n", 97 | " if essai == nombre_secret:\n", 98 | " print(\"Bravo ! Vous avez trouvé le nombre secret.\")\n", 99 | " devine = True\n", 100 | " elif essai < nombre_secret:\n", 101 | " print(\"C'est plus grand.\")\n", 102 | " else:\n", 103 | " print(\"C'est plus petit.\")" 104 | ] 105 | }, 106 | { 107 | "cell_type": "markdown", 108 | "metadata": {}, 109 | "source": [ 110 | "#### **Exercice 4 :**\n", 111 | "\n", 112 | "Écrivez un programme qui affiche les nombres de 1 à 10, mais qui saute le nombre 5." 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": 7, 118 | "metadata": {}, 119 | "outputs": [ 120 | { 121 | "name": "stdout", 122 | "output_type": "stream", 123 | "text": [ 124 | "1\n", 125 | "2\n", 126 | "3\n", 127 | "4\n", 128 | "6\n", 129 | "7\n", 130 | "8\n", 131 | "9\n", 132 | "10\n" 133 | ] 134 | } 135 | ], 136 | "source": [ 137 | "for i in range(1, 11):\n", 138 | " if i == 5:\n", 139 | " continue\n", 140 | " print(i)" 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": {}, 146 | "source": [ 147 | "#### **Exercice 5 :**\n", 148 | "\n", 149 | "Écrivez une fonction `aire_rectangle` qui prend en paramètres la longueur et la largeur d'un rectangle et qui retourne son aire." 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": 8, 155 | "metadata": {}, 156 | "outputs": [ 157 | { 158 | "name": "stdout", 159 | "output_type": "stream", 160 | "text": [ 161 | "L'aire du rectangle est : 15\n" 162 | ] 163 | } 164 | ], 165 | "source": [ 166 | "def aire_rectangle(longueur, largeur):\n", 167 | " return longueur * largeur\n", 168 | "\n", 169 | "# Test de la fonction\n", 170 | "l, L = 5, 3\n", 171 | "print(f\"L'aire du rectangle est : {aire_rectangle(l, L)}\")" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "#### **Exercice 6 :**\n", 179 | "\n", 180 | "Utilisez une fonction lambda pour trier la liste suivante en fonction du deuxième élément de chaque tuple." 181 | ] 182 | }, 183 | { 184 | "cell_type": "code", 185 | "execution_count": 9, 186 | "metadata": {}, 187 | "outputs": [ 188 | { 189 | "name": "stdout", 190 | "output_type": "stream", 191 | "text": [ 192 | "[(10, -1), (5, 0), (4, 1), (1, 2)]\n" 193 | ] 194 | } 195 | ], 196 | "source": [ 197 | "points = [(1, 2), (4, 1), (5, 0), (10, -1)]\n", 198 | "sorted_points = sorted(points, key=lambda point: point[1])\n", 199 | "print(sorted_points)" 200 | ] 201 | }, 202 | { 203 | "cell_type": "markdown", 204 | "metadata": {}, 205 | "source": [ 206 | "#### **Exercice 7 :**\n", 207 | "\n", 208 | "Importez le module `random` et utilisez la fonction `randint` pour générer un nombre entier aléatoire entre 1 et 100." 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": 10, 214 | "metadata": {}, 215 | "outputs": [ 216 | { 217 | "name": "stdout", 218 | "output_type": "stream", 219 | "text": [ 220 | "Nombre aléatoire généré : 45\n" 221 | ] 222 | } 223 | ], 224 | "source": [ 225 | "import random\n", 226 | "\n", 227 | "nombre_aleatoire = random.randint(1, 100)\n", 228 | "print(f\"Nombre aléatoire généré : {nombre_aleatoire}\")" 229 | ] 230 | }, 231 | { 232 | "cell_type": "markdown", 233 | "metadata": {}, 234 | "source": [ 235 | "#### **Exercice 8 :**\n", 236 | "\n", 237 | "Utilisez le module `datetime` pour afficher la date et l'heure actuelles." 238 | ] 239 | }, 240 | { 241 | "cell_type": "code", 242 | "execution_count": 11, 243 | "metadata": {}, 244 | "outputs": [ 245 | { 246 | "name": "stdout", 247 | "output_type": "stream", 248 | "text": [ 249 | "Date et heure actuelles : 2024-10-07 23:35:14.361809\n" 250 | ] 251 | } 252 | ], 253 | "source": [ 254 | "from datetime import datetime\n", 255 | "\n", 256 | "maintenant = datetime.now()\n", 257 | "print(\"Date et heure actuelles :\", maintenant)" 258 | ] 259 | }, 260 | { 261 | "cell_type": "markdown", 262 | "metadata": {}, 263 | "source": [ 264 | "## Exercices Récapitulatifs\n", 265 | "\n", 266 | "### **Exercice 10 : Jeu Pierre-Papier-Ciseaux**\n", 267 | "\n", 268 | "Créez un programme qui permet à l'utilisateur de jouer à Pierre-Papier-Ciseaux contre l'ordinateur.\n", 269 | "\n", 270 | "**Instructions :**\n", 271 | "\n", 272 | "- L'ordinateur fait un choix aléatoire entre \"pierre\", \"papier\" et \"ciseaux\".\n", 273 | "- L'utilisateur saisit son choix.\n", 274 | "- Le programme détermine le gagnant en fonction des règles du jeu.\n", 275 | "- Le programme gère les entrées invalides." 276 | ] 277 | }, 278 | { 279 | "cell_type": "code", 280 | "execution_count": 12, 281 | "metadata": {}, 282 | "outputs": [ 283 | { 284 | "name": "stdout", 285 | "output_type": "stream", 286 | "text": [ 287 | "Ordinateur a choisi : papier\n", 288 | "Vous perdez.\n" 289 | ] 290 | } 291 | ], 292 | "source": [ 293 | "import random\n", 294 | "\n", 295 | "options = [\"pierre\", \"papier\", \"ciseaux\"]\n", 296 | "ordinateur = random.choice(options)\n", 297 | "utilisateur = input(\"Choisissez pierre, papier ou ciseaux : \").lower()\n", 298 | "\n", 299 | "if utilisateur not in options:\n", 300 | " print(\"Choix invalide.\")\n", 301 | "else:\n", 302 | " print(f\"Ordinateur a choisi : {ordinateur}\")\n", 303 | " if utilisateur == ordinateur:\n", 304 | " print(\"Égalité.\")\n", 305 | " elif (utilisateur == \"pierre\" and ordinateur == \"ciseaux\") or \\\n", 306 | " (utilisateur == \"papier\" and ordinateur == \"pierre\") or \\\n", 307 | " (utilisateur == \"ciseaux\" and ordinateur == \"papier\"):\n", 308 | " print(\"Vous gagnez !\")\n", 309 | " else:\n", 310 | " print(\"Vous perdez.\")" 311 | ] 312 | } 313 | ], 314 | "metadata": { 315 | "kernelspec": { 316 | "display_name": "3.12.6", 317 | "language": "python", 318 | "name": "python3" 319 | }, 320 | "language_info": { 321 | "codemirror_mode": { 322 | "name": "ipython", 323 | "version": 3 324 | }, 325 | "file_extension": ".py", 326 | "mimetype": "text/x-python", 327 | "name": "python", 328 | "nbconvert_exporter": "python", 329 | "pygments_lexer": "ipython3", 330 | "version": "3.12.6" 331 | } 332 | }, 333 | "nbformat": 4, 334 | "nbformat_minor": 2 335 | } 336 | -------------------------------------------------------------------------------- /Cours_2_Fonctions_et_modules/Séance 2 - Fonctions et modules.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaouabti/Cours_ENC_Introduction_programmation_Python/7dce58e731a47ba702bba33e292090c8b1e7612d/Cours_2_Fonctions_et_modules/Séance 2 - Fonctions et modules.pdf -------------------------------------------------------------------------------- /Cours_2_Fonctions_et_modules/Séance_2_Fonctions_et_modules.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# **Atelier Pratique : Fonctions et Modules en Python**\n", 8 | "\n", 9 | "---\n", 10 | "Ce notebook est conçu pour vous aider à pratiquer les concepts abordés pendant le cours. Vous y trouverez des explications, des exemples et des exercices pour renforcer votre compréhension des fonctions et des modules en Python.\n", 11 | "\n", 12 | "---\n", 13 | "\n", 14 | "## **Plan du Notebook :**\n", 15 | "\n", 16 | "1. [Révisions](#Révisions)\n", 17 | " - Conditions : `if`, `elif`, `else`\n", 18 | " - Boucles : `for`, `while`\n", 19 | " - Instructions `break` et `continue`\n", 20 | "2. [Les Fonctions en Python](#Les-Fonctions-en-Python)\n", 21 | " - Définition et utilisation\n", 22 | " - Structure d’une fonction\n", 23 | " - Concepts clés et bonnes pratiques\n", 24 | " - Fonctions anonymes (`lambda`)\n", 25 | "3. [Les Modules en Python](#Les-Modules-en-Python)\n", 26 | " - Qu’est-ce qu’un module ?\n", 27 | " - Importation de modules et conventions\n", 28 | " - Quelques modules utiles\n", 29 | " - Création de modules personnalisés\n", 30 | "4. [Exercices Récapitulatifs](#Exercices-Récapitulatifs)\n", 31 | "\n", 32 | "---" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "## Révisions\n", 40 | "\n", 41 | "### Conditions : `if`, `elif`, `else`\n", 42 | "\n", 43 | "Les structures conditionnelles permettent d'exécuter du code de manière sélective en fonction de conditions.\n", 44 | "\n", 45 | "**Syntaxe :**" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": null, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "if condition:\n", 55 | " # Code si la condition est vraie\n", 56 | "elif autre_condition:\n", 57 | " # Code si l'autre condition est vraie\n", 58 | "else:\n", 59 | " # Code si aucune des conditions précédentes n'est vraie" 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "**Exemple :**" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": null, 72 | "metadata": {}, 73 | "outputs": [], 74 | "source": [ 75 | "age = 20\n", 76 | "\n", 77 | "if age >= 18:\n", 78 | " print(\"Vous êtes majeur.\")\n", 79 | "else:\n", 80 | " print(\"Vous êtes mineur.\")" 81 | ] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "metadata": {}, 86 | "source": [ 87 | "#### **Exercice 1 :**\n", 88 | "\n", 89 | "Écrivez un programme qui demande à l'utilisateur d'entrer un nombre et qui indique si ce nombre est positif, négatif ou nul.\n", 90 | "\n", 91 | "*Hint* : utilisez la fontion input()" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": {}, 98 | "outputs": [], 99 | "source": [ 100 | "# Votre code ici" 101 | ] 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "metadata": {}, 106 | "source": [ 107 | "### Boucles : `for`, `while`\n", 108 | "\n", 109 | "#### **Boucle `for`**\n", 110 | "\n", 111 | "La boucle `for` est utilisée pour parcourir les éléments d'une séquence (liste, chaîne de caractères, etc.).\n", 112 | "\n", 113 | "**Syntaxe :**" 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": null, 119 | "metadata": {}, 120 | "outputs": [], 121 | "source": [ 122 | "for élément in séquence:\n", 123 | " # Code à exécuter pour chaque élément" 124 | ] 125 | }, 126 | { 127 | "cell_type": "markdown", 128 | "metadata": {}, 129 | "source": [ 130 | "**Exemple :**" 131 | ] 132 | }, 133 | { 134 | "cell_type": "code", 135 | "execution_count": null, 136 | "metadata": { 137 | "vscode": { 138 | "languageId": "plaintext" 139 | } 140 | }, 141 | "outputs": [], 142 | "source": [ 143 | "fruits = ['pomme', 'banane', 'cerise']\n", 144 | "\n", 145 | "for fruit in fruits:\n", 146 | " print(fruit)" 147 | ] 148 | }, 149 | { 150 | "cell_type": "markdown", 151 | "metadata": {}, 152 | "source": [ 153 | "#### **Exercice 2 :**\n", 154 | "\n", 155 | "Écrivez un programme qui affiche les nombres pairs de 0 à 20." 156 | ] 157 | }, 158 | { 159 | "cell_type": "code", 160 | "execution_count": null, 161 | "metadata": {}, 162 | "outputs": [], 163 | "source": [ 164 | "# Votre code ici\n" 165 | ] 166 | }, 167 | { 168 | "cell_type": "markdown", 169 | "metadata": {}, 170 | "source": [ 171 | "#### **Boucle `while`**\n", 172 | "\n", 173 | "La boucle `while` est utilisée pour répéter du code tant qu'une condition est vraie.\n", 174 | "\n", 175 | "**Syntaxe :**" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": null, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [ 184 | "while condition:\n", 185 | " # Code à exécuter tant que la condition est vraie" 186 | ] 187 | }, 188 | { 189 | "cell_type": "markdown", 190 | "metadata": {}, 191 | "source": [ 192 | "**Exemple :**" 193 | ] 194 | }, 195 | { 196 | "cell_type": "markdown", 197 | "metadata": {}, 198 | "source": [ 199 | "compteur = 0\n", 200 | "\n", 201 | "while compteur < 5:\n", 202 | " print(\"Compteur :\", compteur)\n", 203 | " compteur += 1" 204 | ] 205 | }, 206 | { 207 | "cell_type": "markdown", 208 | "metadata": {}, 209 | "source": [ 210 | "#### **Exercice 3 :**\n", 211 | "\n", 212 | "Écrivez un programme qui demande à l'utilisateur de deviner un nombre secret entre 1 et 10.\n", 213 | "\n", 214 | "*Hint* : utiliser random.randint(1, 10)" 215 | ] 216 | }, 217 | { 218 | "cell_type": "code", 219 | "execution_count": null, 220 | "metadata": {}, 221 | "outputs": [], 222 | "source": [ 223 | "# Votre code ici" 224 | ] 225 | }, 226 | { 227 | "cell_type": "markdown", 228 | "metadata": {}, 229 | "source": [ 230 | "### Instructions `break` et `continue`\n", 231 | "\n", 232 | "#### **`break`**\n", 233 | "\n", 234 | "L'instruction `break` permet de sortir immédiatement d'une boucle.\n", 235 | "\n", 236 | "**Exemple :**" 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": null, 242 | "metadata": {}, 243 | "outputs": [], 244 | "source": [ 245 | "for i in range(10):\n", 246 | " if i == 5:\n", 247 | " break\n", 248 | " print(i)" 249 | ] 250 | }, 251 | { 252 | "cell_type": "markdown", 253 | "metadata": {}, 254 | "source": [ 255 | "#### **`continue`**\n", 256 | "\n", 257 | "L'instruction `continue` permet de passer directement à l'itération suivante de la boucle.\n", 258 | "\n", 259 | "**Exemple :**" 260 | ] 261 | }, 262 | { 263 | "cell_type": "code", 264 | "execution_count": null, 265 | "metadata": {}, 266 | "outputs": [], 267 | "source": [ 268 | "for i in range(10):\n", 269 | " if i % 2 == 0:\n", 270 | " continue\n", 271 | " print(i)" 272 | ] 273 | }, 274 | { 275 | "cell_type": "markdown", 276 | "metadata": {}, 277 | "source": [ 278 | "#### **Exercice 4 :**\n", 279 | "\n", 280 | "Écrivez un programme qui affiche les nombres de 1 à 10, mais qui saute le nombre 5." 281 | ] 282 | }, 283 | { 284 | "cell_type": "code", 285 | "execution_count": null, 286 | "metadata": {}, 287 | "outputs": [], 288 | "source": [ 289 | "# Votre code ici" 290 | ] 291 | }, 292 | { 293 | "cell_type": "markdown", 294 | "metadata": {}, 295 | "source": [ 296 | "---\n", 297 | "## Les Fonctions en Python\n", 298 | "\n", 299 | "### Définition et utilisation\n", 300 | "\n", 301 | "Une fonction est un bloc de code qui réalise une tâche spécifique et qui peut être réutilisé.\n", 302 | "\n", 303 | "**Syntaxe :**" 304 | ] 305 | }, 306 | { 307 | "cell_type": "code", 308 | "execution_count": null, 309 | "metadata": {}, 310 | "outputs": [], 311 | "source": [ 312 | "def nom_de_la_fonction(paramètres):\n", 313 | " # Corps de la fonction\n", 314 | " return valeur_de_retour" 315 | ] 316 | }, 317 | { 318 | "cell_type": "markdown", 319 | "metadata": {}, 320 | "source": [ 321 | "**Exemple :**" 322 | ] 323 | }, 324 | { 325 | "cell_type": "code", 326 | "execution_count": null, 327 | "metadata": {}, 328 | "outputs": [], 329 | "source": [ 330 | "def saluer(nom):\n", 331 | " return f\"Bonjour, {nom} !\"\n", 332 | "\n", 333 | "message = saluer(\"Marion\")\n", 334 | "print(message)" 335 | ] 336 | }, 337 | { 338 | "cell_type": "markdown", 339 | "metadata": {}, 340 | "source": [ 341 | "### Structure d’une fonction\n", 342 | "\n", 343 | "- **Déclaration avec `def`**\n", 344 | "- **Paramètres d'entrée**\n", 345 | "- **Corps de la fonction**\n", 346 | "- **Valeur de retour avec `return`**" 347 | ] 348 | }, 349 | { 350 | "cell_type": "markdown", 351 | "metadata": {}, 352 | "source": [ 353 | "#### **Exercice 5 :**\n", 354 | "\n", 355 | "Écrivez une fonction `aire_rectangle` qui prend en paramètres la longueur et la largeur d'un rectangle et qui retourne son aire." 356 | ] 357 | }, 358 | { 359 | "cell_type": "code", 360 | "execution_count": null, 361 | "metadata": {}, 362 | "outputs": [], 363 | "source": [ 364 | "# Votre code ici" 365 | ] 366 | }, 367 | { 368 | "cell_type": "markdown", 369 | "metadata": {}, 370 | "source": [ 371 | "### Concepts clés et bonnes pratiques pour les fonctions\n", 372 | "\n", 373 | "- **Paramètres vs Arguments**\n", 374 | "- **Portée des variables (locales vs globales)**\n", 375 | "- **Documentation avec les docstrings**\n", 376 | "- **Noms explicites pour les fonctions et paramètres**\n", 377 | "\n", 378 | "**Exemple avec docstring :**" 379 | ] 380 | }, 381 | { 382 | "cell_type": "code", 383 | "execution_count": null, 384 | "metadata": {}, 385 | "outputs": [], 386 | "source": [ 387 | "def multiplier(a, b):\n", 388 | " \"\"\"\n", 389 | " Multiplie deux nombres et retourne le résultat.\n", 390 | " :param a: Premier nombre\n", 391 | " :param b: Deuxième nombre\n", 392 | " :return: Produit de a et b\n", 393 | " \"\"\"\n", 394 | " return a * b" 395 | ] 396 | }, 397 | { 398 | "cell_type": "markdown", 399 | "metadata": {}, 400 | "source": [ 401 | "### Fonction anonyme (`lambda`)\n", 402 | "\n", 403 | "Les fonctions lambda sont des fonctions anonymes, définies en une seule ligne.\n", 404 | "\n", 405 | "**Syntaxe :**" 406 | ] 407 | }, 408 | { 409 | "cell_type": "code", 410 | "execution_count": null, 411 | "metadata": {}, 412 | "outputs": [], 413 | "source": [ 414 | "lambda paramètres : expression" 415 | ] 416 | }, 417 | { 418 | "cell_type": "markdown", 419 | "metadata": {}, 420 | "source": [ 421 | "**Exemple :**" 422 | ] 423 | }, 424 | { 425 | "cell_type": "code", 426 | "execution_count": null, 427 | "metadata": {}, 428 | "outputs": [], 429 | "source": [ 430 | "carré = lambda x: x ** 2\n", 431 | "print(carré(5))" 432 | ] 433 | }, 434 | { 435 | "cell_type": "markdown", 436 | "metadata": {}, 437 | "source": [ 438 | "#### **Exercice 6 :**\n", 439 | "\n", 440 | "Utilisez une fonction lambda pour trier la liste suivante en fonction du deuxième élément de chaque tuple." 441 | ] 442 | }, 443 | { 444 | "cell_type": "code", 445 | "execution_count": null, 446 | "metadata": {}, 447 | "outputs": [], 448 | "source": [ 449 | "# Votre code ici" 450 | ] 451 | }, 452 | { 453 | "cell_type": "markdown", 454 | "metadata": {}, 455 | "source": [ 456 | "---\n", 457 | "## Les Modules en Python\n", 458 | "\n", 459 | "### Qu’est-ce qu’un module ?\n", 460 | "\n", 461 | "Un module est un fichier Python contenant des fonctions, classes et variables regroupées par fonctionnalité.\n", 462 | "\n", 463 | "### Importation de modules et conventions\n", 464 | "\n", 465 | "- **Importation standard :**" 466 | ] 467 | }, 468 | { 469 | "cell_type": "code", 470 | "execution_count": null, 471 | "metadata": {}, 472 | "outputs": [], 473 | "source": [ 474 | "import math\n", 475 | "print(math.pi)" 476 | ] 477 | }, 478 | { 479 | "cell_type": "markdown", 480 | "metadata": {}, 481 | "source": [ 482 | "- **Importation partielle :**" 483 | ] 484 | }, 485 | { 486 | "cell_type": "code", 487 | "execution_count": null, 488 | "metadata": {}, 489 | "outputs": [], 490 | "source": [ 491 | "from math import sqrt\n", 492 | "print(sqrt(16))" 493 | ] 494 | }, 495 | { 496 | "cell_type": "markdown", 497 | "metadata": {}, 498 | "source": [ 499 | "- **Alias avec `as` :**" 500 | ] 501 | }, 502 | { 503 | "cell_type": "code", 504 | "execution_count": null, 505 | "metadata": {}, 506 | "outputs": [], 507 | "source": [ 508 | "import numpy as np" 509 | ] 510 | }, 511 | { 512 | "cell_type": "markdown", 513 | "metadata": {}, 514 | "source": [ 515 | "#### **Exercice 7 :**\n", 516 | "\n", 517 | "Importez le module `random` et utilisez la fonction `randint` pour générer un nombre entier aléatoire entre 1 et 100." 518 | ] 519 | }, 520 | { 521 | "cell_type": "code", 522 | "execution_count": null, 523 | "metadata": {}, 524 | "outputs": [], 525 | "source": [ 526 | "# Votre code ici" 527 | ] 528 | }, 529 | { 530 | "cell_type": "markdown", 531 | "metadata": {}, 532 | "source": [ 533 | "### Quelques modules utiles\n", 534 | "\n", 535 | "- `math` : Fonctions mathématiques\n", 536 | "- `random` : Génération de nombres aléatoires\n", 537 | "- `datetime` : Manipulation des dates et heures\n", 538 | "- `os` : Interactions avec le système d'exploitation\n", 539 | "- `sys` : Accès à certaines variables utilisées ou maintenues par l'interpréteur" 540 | ] 541 | }, 542 | { 543 | "cell_type": "markdown", 544 | "metadata": {}, 545 | "source": [ 546 | "#### **Exercice 8 :**\n", 547 | "\n", 548 | "Utilisez le module `datetime` pour afficher la date et l'heure actuelles." 549 | ] 550 | }, 551 | { 552 | "cell_type": "code", 553 | "execution_count": null, 554 | "metadata": {}, 555 | "outputs": [], 556 | "source": [ 557 | "# Votre code ici" 558 | ] 559 | }, 560 | { 561 | "cell_type": "markdown", 562 | "metadata": {}, 563 | "source": [ 564 | "### Création de modules personnalisés\n", 565 | "\n", 566 | "#### **Étape 1 :** Créer un fichier `mon_module.py`\n", 567 | "\n", 568 | "Placez le code suivant dans un fichier nommé `mon_module.py`." 569 | ] 570 | }, 571 | { 572 | "cell_type": "code", 573 | "execution_count": null, 574 | "metadata": {}, 575 | "outputs": [], 576 | "source": [ 577 | "# mon_module.py\n", 578 | "\n", 579 | "def saluer(nom):\n", 580 | " return f\"Bonjour, {nom} !\"\n", 581 | "\n", 582 | "def addition(a, b):\n", 583 | " return a + b" 584 | ] 585 | }, 586 | { 587 | "cell_type": "markdown", 588 | "metadata": {}, 589 | "source": [ 590 | "import mon_module\n", 591 | "\n", 592 | "print(mon_module.saluer(\"Alice\"))\n", 593 | "print(mon_module.addition(5, 7))" 594 | ] 595 | }, 596 | { 597 | "cell_type": "markdown", 598 | "metadata": {}, 599 | "source": [ 600 | "#### **Étape 2 :** Importer votre module" 601 | ] 602 | }, 603 | { 604 | "cell_type": "code", 605 | "execution_count": null, 606 | "metadata": {}, 607 | "outputs": [], 608 | "source": [ 609 | "import mon_module\n", 610 | "\n", 611 | "print(mon_module.saluer(\"Alice\"))\n", 612 | "print(mon_module.addition(5, 7))" 613 | ] 614 | }, 615 | { 616 | "cell_type": "markdown", 617 | "metadata": {}, 618 | "source": [ 619 | "*Note :* Assurez-vous que le fichier `mon_module.py` est dans le même répertoire que votre notebook." 620 | ] 621 | }, 622 | { 623 | "cell_type": "markdown", 624 | "metadata": {}, 625 | "source": [ 626 | "---\n", 627 | "## Exercices Récapitulatifs\n", 628 | "\n", 629 | "### **Exercice 9 : Jeu Pierre-Papier-Ciseaux**\n", 630 | "\n", 631 | "Créez un programme qui permet à l'utilisateur de jouer à Pierre-Papier-Ciseaux contre l'ordinateur.\n", 632 | "\n", 633 | "**Instructions :**\n", 634 | "\n", 635 | "- L'ordinateur fait un choix aléatoire entre \"pierre\", \"papier\" et \"ciseaux\".\n", 636 | "- L'utilisateur saisit son choix.\n", 637 | "- Le programme détermine le gagnant en fonction des règles du jeu.\n", 638 | "- Le programme gère les entrées invalides." 639 | ] 640 | }, 641 | { 642 | "cell_type": "code", 643 | "execution_count": null, 644 | "metadata": {}, 645 | "outputs": [], 646 | "source": [ 647 | "# Votre code ici" 648 | ] 649 | }, 650 | { 651 | "cell_type": "markdown", 652 | "metadata": {}, 653 | "source": [] 654 | }, 655 | { 656 | "cell_type": "markdown", 657 | "metadata": {}, 658 | "source": [ 659 | "\n", 660 | "\n", 661 | "\n", 662 | "\n", 663 | "```python\n", 664 | "# math_personnalisé.py\n", 665 | "\n", 666 | "def addition(a, b):\n", 667 | " return a + b\n", 668 | "\n", 669 | "def soustraction(a, b):\n", 670 | " return a - b\n", 671 | "\n", 672 | "def multiplication(a, b):\n", 673 | " return a * b\n", 674 | "\n", 675 | "def division(a, b):\n", 676 | " if b != 0:\n", 677 | " return a / b\n", 678 | " else:\n", 679 | " return \"Erreur : Division par zéro\"\n", 680 | "```\n", 681 | "\n", 682 | "2. **Utilisez ce module dans votre programme de calculatrice.**\n", 683 | "\n", 684 | "```python\n", 685 | "# Votre code ici\n", 686 | "import math_personnalisé as mp\n", 687 | "\n", 688 | "print(\"Sélectionnez l'opération :\")\n", 689 | "print(\"1. Addition\")\n", 690 | "print(\"2. Soustraction\")\n", 691 | "print(\"3. Multiplication\")\n", 692 | "print(\"4. Division\")\n", 693 | "\n", 694 | "choix = input(\"Entrez votre choix (1/2/3/4) : \")\n", 695 | "\n", 696 | "num1 = float(input(\"Entrez le premier nombre : \"))\n", 697 | "num2 = float(input(\"Entrez le deuxième nombre : \"))\n", 698 | "\n", 699 | "if choix == '1':\n", 700 | " print(f\"Résultat : {mp.addition(num1, num2)}\")\n", 701 | "elif choix == '2':\n", 702 | " print(f\"Résultat : {mp.soustraction(num1, num2)}\")\n", 703 | "elif choix == '3':\n", 704 | " print(f\"Résultat : {mp.multiplication(num1, num2)}\")\n", 705 | "elif choix == '4':\n", 706 | " print(f\"Résultat : {mp.division(num1, num2)}\")\n", 707 | "else:\n", 708 | " print(\"Choix invalide.\")\n", 709 | "```\n", 710 | "\n", 711 | "*Note :* Assurez-vous que le fichier `math_personnalisé.py` est dans le même répertoire que votre notebook.\n", 712 | "\n", 713 | "---\n", 714 | "\n", 715 | "## **Félicitations !**\n", 716 | "\n", 717 | "Vous avez terminé les exercices de ce notebook. N'hésitez pas à revenir sur les sections précédentes pour réviser ou approfondir les notions abordées.\n", 718 | "\n", 719 | "---\n", 720 | "\n", 721 | "**Ressources supplémentaires :**\n", 722 | "\n", 723 | "- [Documentation officielle Python](https://docs.python.org/3/)\n", 724 | "- [Tutoriels Python sur OpenClassrooms](https://openclassrooms.com/fr/courses/235344-apprenez-a-programmer-en-python)\n", 725 | "- [W3Schools Python Tutorial](https://www.w3schools.com/python/)\n", 726 | "\n", 727 | "---" 728 | ] 729 | } 730 | ], 731 | "metadata": { 732 | "language_info": { 733 | "name": "python" 734 | } 735 | }, 736 | "nbformat": 4, 737 | "nbformat_minor": 2 738 | } 739 | -------------------------------------------------------------------------------- /Cours_3_Introduction_POO/Seance_3_Exercices.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Notebook d'Exercices de Révision en Python et Introduction aux Classes et Objets\n", 8 | "\n", 9 | "---\n", 10 | "\n", 11 | "## Table des Matières\n", 12 | "\n", 13 | "1. [Commentaires de Code](#Commentaires-de-Code)\n", 14 | "2. [Fonctions](#Fonctions)\n", 15 | "3. [Modules](#Modules)\n", 16 | "4. [Introduction aux Classes et Objets](#Introduction-aux-Classes-et-Objets)\n", 17 | " - [Qu'est-ce que la POO ?](#Qu'est-ce-que-la-POO-?)\n", 18 | " - [Les Classes](#Les-Classes)\n", 19 | " - [Les Objets](#Les-Objets)\n", 20 | " - [Les Méthodes et les Attributs](#Les-Méthodes-et-les-Attributs)\n", 21 | " - [Les Attributs de Classe](#Les-Attributs-de-Classe)\n", 22 | " - [Les Attributs d'Instance](#Les-Attributs-d'Instance)\n", 23 | " - [La Méthode `__init__` et le Paramètre `self`](#La-Méthode-__init__-et-le-Paramètre-self)\n", 24 | "\n", 25 | "---" 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "## Commentaires de Code\n", 33 | "\n", 34 | "### Exercice 1 : Utilisation de Docstrings\n", 35 | "\n", 36 | "**Objectif :**\n", 37 | "\n", 38 | "- Ajouter des docstrings à une fonction existante pour améliorer sa documentation.\n", 39 | "\n", 40 | "**Instructions :**\n", 41 | "\n", 42 | "1. Créez une fonction `calculer_facteur` qui prend un nombre entier en paramètre et retourne le double de ce nombre.\n", 43 | "2. Ajoutez une docstring à votre fonction qui décrit ce qu'elle fait, ses paramètres et sa valeur de retour.\n", 44 | "3. Testez votre fonction avec un exemple." 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 107, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [ 53 | "# Votre code ici" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": {}, 59 | "source": [ 60 | "
\n", 61 | "Solution\n", 62 | "\n", 63 | "```python\n", 64 | "\n", 65 | "def calculer_facteur(n):\n", 66 | " \"\"\"\n", 67 | " Cette fonction permet de calculer le double du nombre donné.\n", 68 | "\n", 69 | " Paramètres:\n", 70 | "\n", 71 | " :param n:\n", 72 | " - Trype : float\n", 73 | " - La coordonée du point x.\n", 74 | "\n", 75 | " Retourne:\n", 76 | " int: Le double du nombre fourni.\n", 77 | "\n", 78 | " \n", 79 | " \"\"\"\n", 80 | " return int(n) * 2\n", 81 | "\n", 82 | "# Test de la fonction\n", 83 | "resultat = calculer_facteur(5)\n", 84 | "print(f\"Le double de 5 est {resultat}.\")\n", 85 | "```" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": {}, 91 | "source": [ 92 | "---\n", 93 | "\n", 94 | "### Exercice 2 : Commentaires en Ligne\n", 95 | "\n", 96 | "**Objectif :**\n", 97 | "\n", 98 | "- Utiliser des commentaires en ligne pour expliquer des parties spécifiques du code.\n", 99 | "\n", 100 | "**Instructions :**\n", 101 | "\n", 102 | "1. Écrivez un code qui calcule la somme des nombres pairs de 1 à 20.\n", 103 | "2. Ajoutez des commentaires en ligne pour expliquer chaque étape de votre code." 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": 108, 109 | "metadata": {}, 110 | "outputs": [], 111 | "source": [ 112 | "# Votre code ici" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "
\n", 120 | "Solution\n", 121 | "\n", 122 | "```python\n", 123 | "somme = 0 # Initialisation de la variable somme\n", 124 | "\n", 125 | "for i in range(1, 21):\n", 126 | " if i % 2 == 0:\n", 127 | " somme += i # Ajout du nombre pair à la somme\n", 128 | "\n", 129 | "print(f\"La somme des nombres pairs de 1 à 20 est {somme}.\")\n", 130 | "```" 131 | ] 132 | }, 133 | { 134 | "cell_type": "markdown", 135 | "metadata": {}, 136 | "source": [ 137 | "---\n", 138 | "\n", 139 | "## Fonctions\n", 140 | "\n", 141 | "### Exercice 3 : Création de Fonctions\n", 142 | "\n", 143 | "**Objectif :**\n", 144 | "\n", 145 | "- Créer une fonction pour déterminer si un nombre est premier.\n", 146 | "\n", 147 | "**Instructions :**\n", 148 | "\n", 149 | "1. Créez une fonction `est_premier` qui prend un nombre entier en paramètre.\n", 150 | "2. La fonction doit retourner `True` si le nombre est premier, `False` sinon.\n", 151 | "3. Ajoutez une docstring à votre fonction.\n", 152 | "4. Testez votre fonction avec plusieurs exemples.\n", 153 | "\n", 154 | "*Tips* : Un nombre premier est divisible uniquement par lui-même et par 1" 155 | ] 156 | }, 157 | { 158 | "cell_type": "code", 159 | "execution_count": 109, 160 | "metadata": {}, 161 | "outputs": [], 162 | "source": [ 163 | "# Votre code ici" 164 | ] 165 | }, 166 | { 167 | "cell_type": "markdown", 168 | "metadata": {}, 169 | "source": [ 170 | "
\n", 171 | "Solution\n", 172 | "\n", 173 | "```python\n", 174 | "def est_premier(n):\n", 175 | " \"\"\"\n", 176 | " Vérifie si un nombre est premier.\n", 177 | "\n", 178 | " Paramètres:\n", 179 | " n (int): Le nombre à vérifier.\n", 180 | "\n", 181 | " Retourne:\n", 182 | " bool: True si le nombre est premier, False sinon.\n", 183 | " \"\"\"\n", 184 | " if n <= 1:\n", 185 | " return False\n", 186 | " for i in range(2, n):\n", 187 | " if n % i == 0:\n", 188 | " return False\n", 189 | " return True\n", 190 | "\n", 191 | "# Tests\n", 192 | "print(est_premier(7)) # True\n", 193 | "print(est_premier(10)) # False\n", 194 | "print(est_premier(13)) # True\n", 195 | "```\n", 196 | "\n", 197 | "*Sortie :*\n", 198 | "\n", 199 | "```\n", 200 | "True\n", 201 | "False\n", 202 | "True\n", 203 | "```\n", 204 | "\n", 205 | "Fonctionne aussi avec la version Fermat :\n", 206 | "\n", 207 | "``` python\n", 208 | "def test_Fermat(n):\n", 209 | " \"\"\"\n", 210 | " Vérifie si un nombre est premier en s'appuyant sur le petit théorème de Fermat.\n", 211 | " Pour en savoir plus : https://fr.wikipedia.org/wiki/Petit_th%C3%A9or%C3%A8me_de_Fermat\n", 212 | "\n", 213 | " Paramètres:\n", 214 | " n (int): Le nombre à vérifier.\n", 215 | "\n", 216 | " Retourne:\n", 217 | " bool: True si le nombre est premier, False sinon.\n", 218 | " \"\"\"\n", 219 | " if 2**n-1 % n == 1:\n", 220 | " return True\n", 221 | " else:\n", 222 | " return False\n", 223 | "\n", 224 | "n = 221\n", 225 | "test_Fermat(n)\n", 226 | "```\n", 227 | "
\n", 228 | "\n", 229 | "\n" 230 | ] 231 | }, 232 | { 233 | "cell_type": "markdown", 234 | "metadata": {}, 235 | "source": [ 236 | "---\n", 237 | "\n", 238 | "### Exercice 4 : Utilisation de `filter()` et de la fonction `lambda`\n", 239 | "\n", 240 | "**Objectif :**\n", 241 | "\n", 242 | "- Utiliser la fonction `filter()` pour sélectionner des événements historiques en fonction d'une condition spécifique.\n", 243 | "\n", 244 | "**Instructions :**\n", 245 | "\n", 246 | "1. Vous avez une liste de tuples représentant des événements historiques avec leur date :\n", 247 | " ```python\n", 248 | " evenements = [('Bataille de Qadesh', -1274), ('Aristote en latin', 1206), ('Hégire', 622), ('Chute de Babylone', -539), ('Découverte de l\\'Amérique', 1492), ('Révolution Française', 1789)]\n", 249 | " ```\n", 250 | " \n", 251 | "2. Utilisez la fonction `filter()` et une fonction lambda pour filtrer uniquement les événements qui se sont déroulés après l'an 0 (événements historiques modernes).\n", 252 | " \n", 253 | "3. Affichez la liste des événements filtrés." 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": 110, 259 | "metadata": {}, 260 | "outputs": [], 261 | "source": [ 262 | "# Votre code ici" 263 | ] 264 | }, 265 | { 266 | "cell_type": "markdown", 267 | "metadata": {}, 268 | "source": [ 269 | "**Note sur la fonction `filter()`**\n", 270 | "\n", 271 | "\n", 272 | "La fonction filter() retourne un itérateur, c'est pourquoi on obtient un résultat du type \"\" si on ne le transforme pas en liste. Un itérateur ne conserve aucune donnée et ne produit les résultats que lorsqu'on les appelle. Si on le convertit en liste, cela signifie qu'on demande à l'itérateur de nous produire une liste de ses résultats.\n", 273 | "\n", 274 | "Un itérateur se comporte un peu comme une boucle for, mais il ne conserve pas les éléments tant que vous ne les avez pas appelés. Cela permet de fournir les éléments à la demande, ce qui est particulièrement utile pour travailler avec de grandes quantités de données sans consommer trop de mémoire." 275 | ] 276 | }, 277 | { 278 | "cell_type": "markdown", 279 | "metadata": {}, 280 | "source": [ 281 | "
\n", 282 | "Solution\n", 283 | "\n", 284 | "```python\n", 285 | "# Liste des événements historiques\n", 286 | "\n", 287 | "evenements = [\n", 288 | " ('Bataille de Qadesh', -1274),\n", 289 | " ('Aristote en latin', 1206),\n", 290 | " ('Hégire', 622),\n", 291 | " ('Chute de Babylone', -539),\n", 292 | " ('Découverte de l\\'Amérique', 1492),\n", 293 | " ('Révolution Française', 1789)\n", 294 | "]\n", 295 | "\n", 296 | "# Utilisation de filter() pour filtrer les événements après l'an 0\n", 297 | "evenements_modernes = list(filter(lambda event: event[1] > 0, evenements))\n", 298 | "print(f\"Événements modernes :{evenements_modernes}\")\n", 299 | "```\n", 300 | "\n", 301 | "*Sortie :*\n", 302 | "\n", 303 | "```\n", 304 | "Événements modernes :\n", 305 | "('Aristote en latin', 1206)\n", 306 | "('Hégire', 622)\n", 307 | "('Découverte de l'Amérique', 1492)\n", 308 | "('Révolution Française', 1789)\n", 309 | "```\n", 310 | "
" 311 | ] 312 | }, 313 | { 314 | "cell_type": "markdown", 315 | "metadata": {}, 316 | "source": [ 317 | "---\n", 318 | "\n", 319 | "## Modules\n", 320 | "\n", 321 | "### Exercice 5 : Création d'un Module Historique Personnalisé\n", 322 | "\n", 323 | "**Objectif :**\n", 324 | "\n", 325 | "- Créer un module personnalisé lié à l'histoire et l'importer dans votre code.\n", 326 | "\n", 327 | "**Instructions :**\n", 328 | "\n", 329 | "1. Créez un fichier nommé `histoire_utils.py`.\n", 330 | "2. Dans ce module, définissez une fonction `calculer_ecart_annees(date1, date2)` qui calcule le nombre d'années écoulées entre deux dates historiques.\n", 331 | "3. Importez cette fonction dans votre notebook et utilisez-la pour calculer le nombre d'années entre deux événements historiques de votre choix (par exemple, entre la Révolution française en 1789 et le début de la Première Guerre mondiale en 1914).\n", 332 | "4. Documentez votre fonction avec une docstring.\n", 333 | "\n", 334 | "\n", 335 | "*(Note : Si vous ne voulez pas créer de fichiers sur votre ordi, vous pouvez lancer le notebook dans GoogleColab : https://colab.research.google.com/)*" 336 | ] 337 | }, 338 | { 339 | "cell_type": "code", 340 | "execution_count": 119, 341 | "metadata": {}, 342 | "outputs": [], 343 | "source": [ 344 | "# Votre code ici" 345 | ] 346 | }, 347 | { 348 | "cell_type": "markdown", 349 | "metadata": {}, 350 | "source": [ 351 | "
\n", 352 | "Solution\n", 353 | "\n", 354 | "```python\n", 355 | "# Simuler le contenu du module histoire_utils.py\n", 356 | "def calculer_ecart_annees(date1, date2):\n", 357 | " \"\"\"\n", 358 | " Calcule le nombre d'années écoulées entre deux dates historiques.\n", 359 | " \n", 360 | " Paramètres:\n", 361 | " date1 (int): La première date historique.\n", 362 | " date2 (int): La deuxième date historique.\n", 363 | " \n", 364 | " Retourne:\n", 365 | " int: Le nombre d'années entre les deux dates.\n", 366 | " \"\"\"\n", 367 | " return abs(date2 - date1)\n", 368 | "\n", 369 | "# Importation de la fonction depuis le module\n", 370 | "from histoire_utils import calculer_ecart_annees\n", 371 | "\n", 372 | "# Exemple d'utilisation\n", 373 | "evenement1 = (\"Fondation de Constantinople\", 330)\n", 374 | "evenement2 = (\"Chute de l'empire Byzantin\", 1453)\n", 375 | "\n", 376 | "ecart = calculer_ecart_annees(evenement1[1], evenement2[1])\n", 377 | "\n", 378 | "print(f\"Il y a {ecart} ans entre {evenement1[0]} et {evenement2[0]}.\")\n", 379 | "```\n", 380 | "\n", 381 | "*Sortie :*\n", 382 | "\n", 383 | "```\n", 384 | "Il y a 1123 ans entre Fondation de Constantinople et Chute de l'empire Byzantin.\n", 385 | "```\n", 386 | "\n", 387 | "
" 388 | ] 389 | }, 390 | { 391 | "cell_type": "markdown", 392 | "metadata": {}, 393 | "source": [ 394 | "---\n", 395 | "\n", 396 | "## Introduction aux Classes et Objets\n", 397 | "\n", 398 | "### Exercice 6 : Création d'une Classe Simple\n", 399 | "\n", 400 | "**Objectif :**\n", 401 | "\n", 402 | "- Créer une classe `Livre` avec des attributs d'instance.\n", 403 | "\n", 404 | "**Instructions :**\n", 405 | "\n", 406 | "1. Créez une classe `Livre` avec les attributs `titre`, `auteur` et `annee_publication`.\n", 407 | "2. La méthode `__init__` doit initialiser ces attributs.\n", 408 | "3. Ajoutez une méthode `afficher_details` qui affiche les informations du livre.\n", 409 | "4. Instanciez un objet de cette classe avec les informations de votre choix et appelez la méthode `afficher_details`." 410 | ] 411 | }, 412 | { 413 | "cell_type": "code", 414 | "execution_count": 113, 415 | "metadata": {}, 416 | "outputs": [], 417 | "source": [ 418 | "# Votre code ici" 419 | ] 420 | }, 421 | { 422 | "cell_type": "markdown", 423 | "metadata": {}, 424 | "source": [ 425 | "
\n", 426 | "Solution\n", 427 | "\n", 428 | "```python\n", 429 | "class Livre:\n", 430 | " def __init__(self, titre, auteur, annee_publication):\n", 431 | " self.titre = titre\n", 432 | " self.auteur = auteur\n", 433 | " self.annee_publication = annee_publication\n", 434 | "\n", 435 | " def afficher_details(self):\n", 436 | " print(f\"Titre : {self.titre}\")\n", 437 | " print(f\"Auteur : {self.auteur}\")\n", 438 | " print(f\"Année de publication : {self.annee_publication}\")\n", 439 | "\n", 440 | "# Instanciation\n", 441 | "livre1 = Livre(\"Les Misérables\", \"Victor Hugo\", 1862)\n", 442 | "livre1.afficher_details()\n", 443 | "```\n", 444 | "\n", 445 | "*Sortie :*\n", 446 | "\n", 447 | "```\n", 448 | "Titre : Les Misérables\n", 449 | "Auteur : Victor Hugo\n", 450 | "Année de publication : 1862\n", 451 | "```\n", 452 | "
" 453 | ] 454 | }, 455 | { 456 | "cell_type": "markdown", 457 | "metadata": {}, 458 | "source": [ 459 | "---\n", 460 | "\n", 461 | "### Exercice 7 : Attributs de Classe vs Attributs d'Instance\n", 462 | "\n", 463 | "**Objectif :**\n", 464 | "\n", 465 | "- Comprendre la différence entre attributs de classe et attributs d'instance.\n", 466 | "\n", 467 | "**Instructions :**\n", 468 | "\n", 469 | "1. Modifiez la classe `Livre` pour ajouter un attribut de classe `categorie` avec la valeur \"Littérature\".\n", 470 | "2. Créez deux instances de la classe `Livre` avec des titres différents.\n", 471 | "3. Affichez l'attribut de classe `categorie` pour chaque instance.\n", 472 | "4. Modifiez l'attribut de classe `categorie` à \"Roman\" en utilisant la classe.\n", 473 | "5. Affichez à nouveau l'attribut `categorie` pour chaque instance." 474 | ] 475 | }, 476 | { 477 | "cell_type": "code", 478 | "execution_count": 114, 479 | "metadata": {}, 480 | "outputs": [], 481 | "source": [ 482 | "# Votre code ici (vous pouvez réutiliser la classe Livre de l'exercice précédent)" 483 | ] 484 | }, 485 | { 486 | "cell_type": "markdown", 487 | "metadata": {}, 488 | "source": [ 489 | "
\n", 490 | "Solution\n", 491 | "\n", 492 | "```python\n", 493 | "class Livre:\n", 494 | " categorie = \"Littérature\" # Attribut de classe\n", 495 | "\n", 496 | " def __init__(self, titre, auteur, annee_publication):\n", 497 | " self.titre = titre\n", 498 | " self.auteur = auteur\n", 499 | " self.annee_publication = annee_publication\n", 500 | "\n", 501 | " def afficher_details(self):\n", 502 | " print(f\"Titre : {self.titre}\")\n", 503 | " print(f\"Auteur : {self.auteur}\")\n", 504 | " print(f\"Année de publication : {self.annee_publication}\")\n", 505 | " print(f\"Catégorie : {self.categorie}\")\n", 506 | "\n", 507 | "# Instanciation\n", 508 | "livre1 = Livre(\"Les Misérables\", \"Victor Hugo\", 1862)\n", 509 | "livre2 = Livre(\"Le Comte de Monte-Cristo\", \"Alexandre Dumas\", 1844)\n", 510 | "\n", 511 | "# Affichage de la catégorie avant modification\n", 512 | "livre1.afficher_details()\n", 513 | "livre2.afficher_details()\n", 514 | "\n", 515 | "# Modification de l'attribut de classe\n", 516 | "Livre.categorie = \"Roman\"\n", 517 | "\n", 518 | "# Affichage de la catégorie après modification\n", 519 | "print(\"\\nAprès modification de la catégorie :\\n\")\n", 520 | "livre1.afficher_details()\n", 521 | "livre2.afficher_details()\n", 522 | "```\n", 523 | "\n", 524 | "*Sortie :*\n", 525 | "\n", 526 | "```\n", 527 | "Titre : Les Misérables\n", 528 | "Auteur : Victor Hugo\n", 529 | "Année de publication : 1862\n", 530 | "Catégorie : Littérature\n", 531 | "Titre : Le Comte de Monte-Cristo\n", 532 | "Auteur : Alexandre Dumas\n", 533 | "Année de publication : 1844\n", 534 | "Catégorie : Littérature\n", 535 | "\n", 536 | "Après modification de la catégorie :\n", 537 | "\n", 538 | "Titre : Les Misérables\n", 539 | "Auteur : Victor Hugo\n", 540 | "Année de publication : 1862\n", 541 | "Catégorie : Roman\n", 542 | "Titre : Le Comte de Monte-Cristo\n", 543 | "Auteur : Alexandre Dumas\n", 544 | "Année de publication : 1844\n", 545 | "Catégorie : Roman\n", 546 | "```\n", 547 | "
" 548 | ] 549 | }, 550 | { 551 | "cell_type": "markdown", 552 | "metadata": {}, 553 | "source": [ 554 | "---\n", 555 | "\n", 556 | "### Exercice 8 : Utilisation de `__init__` et `self`\n", 557 | "\n", 558 | "**Objectif :**\n", 559 | "\n", 560 | "- Pratiquer l'initialisation des attributs d'instance avec `__init__` et `self`.\n", 561 | "\n", 562 | "**Instructions :**\n", 563 | "\n", 564 | "1. Créez une classe `Gladiateur` avec les attributs `nom`, `origine` et `force`.\n", 565 | "2. La méthode `__init__` doit initialiser ces attributs.\n", 566 | "3. Ajoutez une méthode `présenter_gladiateur` qui affiche les informations du gladiateur.\n", 567 | "4. Instanciez un objet de cette classe et appelez la méthode `présenter_gladiateur`." 568 | ] 569 | }, 570 | { 571 | "cell_type": "code", 572 | "execution_count": 115, 573 | "metadata": {}, 574 | "outputs": [], 575 | "source": [ 576 | "# Votre code ici" 577 | ] 578 | }, 579 | { 580 | "cell_type": "markdown", 581 | "metadata": {}, 582 | "source": [ 583 | "
\n", 584 | "Solution\n", 585 | "\n", 586 | "```python\n", 587 | "class Gladiateur:\n", 588 | " def __init__(self, nom, origine, force):\n", 589 | " self.nom = nom\n", 590 | " self.origine = origine\n", 591 | " self.force = force\n", 592 | "\n", 593 | " def presenter_gladiateur(self):\n", 594 | " print(f\"Nom : {self.nom}\")\n", 595 | " print(f\"Origine : {self.origine}\")\n", 596 | " print(f\"Force : {self.force}\")\n", 597 | "\n", 598 | "# Instanciation\n", 599 | "gladiateur1 = Gladiateur(\"Spartacus\", \"Thrace\", 95)\n", 600 | "gladiateur1.presenter_gladiateur()\n", 601 | "```\n", 602 | "\n", 603 | "*Sortie :*\n", 604 | "\n", 605 | "```\n", 606 | "Nom : Spartacus\n", 607 | "Origine : Thrace\n", 608 | "Force : 95\n", 609 | "```\n", 610 | "\n", 611 | "\n", 612 | "
" 613 | ] 614 | }, 615 | { 616 | "cell_type": "markdown", 617 | "metadata": {}, 618 | "source": [ 619 | "---\n", 620 | "\n", 621 | "### Exercice 9 : Méthodes d'Instance\n", 622 | "\n", 623 | "**Objectif :**\n", 624 | "\n", 625 | "- Ajouter des méthodes d'instance pour modifier l'état d'un objet.\n", 626 | "\n", 627 | "**Instructions :**\n", 628 | "\n", 629 | "1. À partir de la classe `Gladiateur`, ajoutez une méthode `entrainer` qui augmente l'attribut `force` du gladiateur d'un certain montant.\n", 630 | "2. Ajoutez une méthode `évaluer_niveau` qui retourne :\n", 631 | " - \"Champion\" si la force est supérieure ou égale à 90.\n", 632 | " - \"Combattant expérimenté\" si la force est entre 70 et 89.\n", 633 | " - \"Débutant\" si la force est inférieure à 70.\n", 634 | "3. Testez ces méthodes avec différents exemples." 635 | ] 636 | }, 637 | { 638 | "cell_type": "code", 639 | "execution_count": 116, 640 | "metadata": {}, 641 | "outputs": [], 642 | "source": [ 643 | "# Votre code ici (poursuivez avec la classe Gladiateur)" 644 | ] 645 | }, 646 | { 647 | "cell_type": "markdown", 648 | "metadata": {}, 649 | "source": [ 650 | "
\n", 651 | "Solution\n", 652 | "\n", 653 | "```python\n", 654 | "class Gladiateur:\n", 655 | " def __init__(self, nom, origine, force):\n", 656 | " self.nom = nom\n", 657 | " self.origine = origine\n", 658 | " self.force = force\n", 659 | "\n", 660 | " def presenter_gladiateur(self):\n", 661 | " print(f\"Nom : {self.nom}\")\n", 662 | " print(f\"Origine : {self.origine}\")\n", 663 | " print(f\"Force : {self.force}\")\n", 664 | "\n", 665 | " def entrainer(self, augmentation):\n", 666 | " self.force += augmentation\n", 667 | " print(f\"{self.nom} s'est entraîné et sa force est maintenant de {self.force}.\")\n", 668 | "\n", 669 | " def evaluer_niveau(self):\n", 670 | " if self.force >= 90:\n", 671 | " return \"Champion\"\n", 672 | " elif 70 <= self.force < 90:\n", 673 | " return \"Combattant expérimenté\"\n", 674 | " else:\n", 675 | " return \"Débutant\"\n", 676 | "\n", 677 | "# Test\n", 678 | "gladiateur1 = Gladiateur(\"Spartacus\", \"Thrace\", 65)\n", 679 | "gladiateur1.presenter_gladiateur()\n", 680 | "print(f\"Niveau : {gladiateur1.evaluer_niveau()}\")\n", 681 | "\n", 682 | "# Entraînement\n", 683 | "gladiateur1.entrainer(10)\n", 684 | "print(f\"Niveau : {gladiateur1.evaluer_niveau()}\")\n", 685 | "\n", 686 | "gladiateur1.entrainer(20)\n", 687 | "print(f\"Niveau : {gladiateur1.evaluer_niveau()}\")\n", 688 | "```\n", 689 | "\n", 690 | "*Sortie :*\n", 691 | "\n", 692 | "```\n", 693 | "Nom : Spartacus\n", 694 | "Origine : Thrace\n", 695 | "Force : 65\n", 696 | "Niveau : Débutant\n", 697 | "Spartacus s'est entraîné et sa force est maintenant de 75.\n", 698 | "Niveau : Combattant expérimenté\n", 699 | "Spartacus s'est entraîné et sa force est maintenant de 95.\n", 700 | "Niveau : Champion\n", 701 | "```\n", 702 | "\n", 703 | "
" 704 | ] 705 | } 706 | ], 707 | "metadata": { 708 | "kernelspec": { 709 | "display_name": "3.12.6", 710 | "language": "python", 711 | "name": "python3" 712 | }, 713 | "language_info": { 714 | "codemirror_mode": { 715 | "name": "ipython", 716 | "version": 3 717 | }, 718 | "file_extension": ".py", 719 | "mimetype": "text/x-python", 720 | "name": "python", 721 | "nbconvert_exporter": "python", 722 | "pygments_lexer": "ipython3", 723 | "version": "3.12.6" 724 | } 725 | }, 726 | "nbformat": 4, 727 | "nbformat_minor": 2 728 | } 729 | -------------------------------------------------------------------------------- /Cours_3_Introduction_POO/Séance 3 - Programmation orientée objet 1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaouabti/Cours_ENC_Introduction_programmation_Python/7dce58e731a47ba702bba33e292090c8b1e7612d/Cours_3_Introduction_POO/Séance 3 - Programmation orientée objet 1.pdf -------------------------------------------------------------------------------- /Cours_3_Introduction_POO/Séance_3_Base_Programmation_Orientée_Objet.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Séance 3 - Base de la Programmation Orientée Objet\n", 8 | "\n", 9 | "---" 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "## Table des Matières\n", 17 | "\n", 18 | "1. [Révisions](#Révisions)\n", 19 | " - [Commentaires de code](#Commentaires-de-code)\n", 20 | " - [Pourquoi commenter son code ?](#Pourquoi-commenter-son-code-?)\n", 21 | " - [Commentaire docstring (`\"\"\"...\"\"\"`)](#Commentaire-docstring)\n", 22 | " - [Commentaire en ligne (`#`)](#Commentaire-en-ligne)\n", 23 | " - [Fonctions](#Fonctions)\n", 24 | " - [Importance des fonctions](#Importance-des-fonctions)\n", 25 | " - [Structure d'une fonction](#Structure-d'une-fonction)\n", 26 | " - [Fonction lambda](#Fonction-lambda)\n", 27 | " - [Modules](#Modules)\n", 28 | " - [Rappels](#Rappels)\n", 29 | " - [Le fichier `__init__.py`](#Le-fichier-__init__.py)\n", 30 | " - [Import de modules](#Import-de-modules)\n", 31 | "2. [Introduction aux Classes et Objets](#Introduction-aux-Classes-et-Objets)\n", 32 | " - [Qu'est-ce que la POO ?](#Qu'est-ce-que-la-POO-?)\n", 33 | " - [Les Classes](#Les-Classes)\n", 34 | " - [Les Objets](#Les-Objets)\n", 35 | " - \n", 36 | "3. [Les Méthodes et les Attributs](#Les-Méthodes-et-les-Attributs)\n", 37 | " - [Les Attributs d'Instance](#Les-Attributs-d'Instance)\n", 38 | " - [Les Attributs de Classe](#Les-Attributs-de-Classe)\n", 39 | " - [La Méthode `__init__` et le Paramètre `self`](#La-Méthode-__init__-et-le-Paramètre-self)\n", 40 | "3. [Exemples Pratiques et Exercices](#Exemples-Pratiques-et-Exercices)\n", 41 | "\n", 42 | "---" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": { 48 | "vscode": { 49 | "languageId": "plaintext" 50 | } 51 | }, 52 | "source": [ 53 | "## Révisions\n", 54 | "\n", 55 | "### Commentaires de code\n", 56 | "\n", 57 | "#### Pourquoi commenter son code ?\n", 58 | "\n", 59 | "Les commentaires sont des notes que vous laissez dans votre code pour expliquer ce qu'il fait. Ils ne sont pas exécutés par l'interpréteur Python, mais ils sont essentiels pour :\n", 60 | "\n", 61 | "- **Améliorer la lisibilité et la compréhension** : Aider les autres (et vous-même) à comprendre ce que fait le code.\n", 62 | "- **Faciliter la maintenance et la collaboration** : Rendre le code plus facile à mettre à jour et à partager avec d'autres développeurs.\n", 63 | "- **Servir de documentation** : Expliquer les fonctionnalités, les paramètres et les retours des fonctions ou classes.\n", 64 | "\n", 65 | "#### Commentaire docstring\n", 66 | "\n", 67 | "Les **docstrings** sont des chaînes de documentation placées juste après la définition d'une fonction, d'une classe ou d'un module. Elles sont définies entre triple guillemets (`\"\"\"...\"\"\"`) et peuvent s'étendre sur plusieurs lignes." 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "##### Exemple :" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 19, 80 | "metadata": {}, 81 | "outputs": [], 82 | "source": [ 83 | "def analyser_texte(texte):\n", 84 | " \"\"\"\n", 85 | " Analyse un texte donné et retourne le nombre de mots.\n", 86 | "\n", 87 | " Paramètres:\n", 88 | " :param texte (str): \n", 89 | " - Type: str\n", 90 | " - Description Le texte à analyser.\n", 91 | "\n", 92 | " Retourne:\n", 93 | " - Type : int\n", 94 | " - Description : Le nombre de mots dans le texte.\n", 95 | " \"\"\"\n", 96 | " mots = texte.split()\n", 97 | " return len(mots)" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "#### Commentaire en ligne\n", 105 | "\n", 106 | "Les commentaires en ligne commencent par le symbole `#` et s'étendent jusqu'à la fin de la ligne. Ils sont utilisés pour expliquer des parties spécifiques du code." 107 | ] 108 | }, 109 | { 110 | "cell_type": "markdown", 111 | "metadata": {}, 112 | "source": [ 113 | "##### Exemple :" 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": 20, 119 | "metadata": {}, 120 | "outputs": [], 121 | "source": [ 122 | "# Initialisation de la liste des événements historiques\n", 123 | "evenements = []\n", 124 | "\n", 125 | "# Ajout d'un événement à la liste\n", 126 | "evenements.append(\"Chute de l'Empire romain en 476\")" 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "---\n", 134 | "\n", 135 | "### Fonctions\n", 136 | "\n", 137 | "#### Importance des fonctions\n", 138 | "\n", 139 | "Les fonctions permettent de :\n", 140 | "\n", 141 | "- **Modulariser le code** : Diviser le code en blocs réutilisables.\n", 142 | "- **Réduire la redondance** : Éviter de répéter le même code plusieurs fois.\n", 143 | "- **Améliorer la lisibilité** : Rendre le code plus facile à comprendre.\n", 144 | "\n", 145 | "#### Structure d'une fonction\n", 146 | "\n", 147 | "Une fonction en Python est définie avec le mot-clé `def`, suivi du nom de la fonction et des parenthèses contenant éventuellement des paramètres.\n", 148 | "\n", 149 | "##### Syntaxe de base :" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": 21, 155 | "metadata": {}, 156 | "outputs": [], 157 | "source": [ 158 | "def nom_de_la_fonction(paramètre1, paramètre2):\n", 159 | " # Bloc de code de la fonction\n", 160 | " resultat = ''\n", 161 | " return resultat" 162 | ] 163 | }, 164 | { 165 | "cell_type": "markdown", 166 | "metadata": {}, 167 | "source": [ 168 | "##### Exemple :" 169 | ] 170 | }, 171 | { 172 | "cell_type": "code", 173 | "execution_count": 22, 174 | "metadata": {}, 175 | "outputs": [], 176 | "source": [ 177 | "def calculer_annees_regne(date1, date2):\n", 178 | " \"\"\"\n", 179 | " Calcule le nombre d'années entre deux dates.\n", 180 | "\n", 181 | " Paramètres:\n", 182 | " date1 (int): La première date.\n", 183 | " date2 (int): La deuxième date.\n", 184 | "\n", 185 | " Retourne:\n", 186 | " int: Le nombre d'années entre les deux dates.\n", 187 | " \"\"\"\n", 188 | " return abs(date2 - date1)" 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "metadata": {}, 194 | "source": [ 195 | "#### Fonction lambda\n", 196 | "\n", 197 | "Les **fonctions lambda** sont des fonctions anonymes, définies en une seule ligne avec le mot-clé `lambda`. Elles sont souvent utilisées pour des opérations simples.\n", 198 | "\n", 199 | "##### Syntaxe :\n", 200 | "\n", 201 | "lambda paramètres: expression" 202 | ] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": {}, 207 | "source": [ 208 | "##### Exemple :" 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": 23, 214 | "metadata": {}, 215 | "outputs": [ 216 | { 217 | "name": "stdout", 218 | "output_type": "stream", 219 | "text": [ 220 | "15\n" 221 | ] 222 | } 223 | ], 224 | "source": [ 225 | "# Fonction lambda pour ajouter 10 à un nombre\n", 226 | "ajouter_dix = lambda x: x + 10\n", 227 | "print(ajouter_dix(5)) # Affiche 15" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": {}, 233 | "source": [ 234 | "---\n", 235 | "\n", 236 | "### Modules\n", 237 | "\n", 238 | "#### Rappels\n", 239 | "\n", 240 | "Un **module** est un fichier Python contenant du code (fonctions, classes, variables) que vous pouvez réutiliser dans d'autres scripts en l'important. Les modules permettent de :\n", 241 | "\n", 242 | "- **Organiser le code** : Structurer le code en parties logiques.\n", 243 | "- **Réutiliser le code** : Importer des fonctions ou classes dans plusieurs scripts.\n", 244 | "\n", 245 | "#### Le fichier `__init__.py`\n", 246 | "\n", 247 | "Le fichier `__init__.py` est utilisé pour indiquer qu'un répertoire doit être traité comme un **package** Python. Il peut être vide ou contenir du code d'initialisation pour le package.\n", 248 | "\n", 249 | "##### Exemple de structure de package :\n", 250 | "\n", 251 | "```\n", 252 | "mon_package/\n", 253 | "├── __init__.py\n", 254 | "├── module1.py\n", 255 | "└── module2.py\n", 256 | "```\n", 257 | "\n", 258 | "#### Import de modules\n", 259 | "\n", 260 | "Il existe plusieurs façons d'importer des modules en Python.\n", 261 | "\n", 262 | "##### Importation standard" 263 | ] 264 | }, 265 | { 266 | "cell_type": "code", 267 | "execution_count": 24, 268 | "metadata": {}, 269 | "outputs": [ 270 | { 271 | "name": "stdout", 272 | "output_type": "stream", 273 | "text": [ 274 | "3.141592653589793\n" 275 | ] 276 | } 277 | ], 278 | "source": [ 279 | "import math\n", 280 | "\n", 281 | "print(math.pi)" 282 | ] 283 | }, 284 | { 285 | "cell_type": "markdown", 286 | "metadata": {}, 287 | "source": [ 288 | "##### Importation spécifique" 289 | ] 290 | }, 291 | { 292 | "cell_type": "code", 293 | "execution_count": 25, 294 | "metadata": {}, 295 | "outputs": [ 296 | { 297 | "name": "stdout", 298 | "output_type": "stream", 299 | "text": [ 300 | "3.141592653589793\n" 301 | ] 302 | } 303 | ], 304 | "source": [ 305 | "from math import pi\n", 306 | "\n", 307 | "print(pi)" 308 | ] 309 | }, 310 | { 311 | "cell_type": "markdown", 312 | "metadata": {}, 313 | "source": [ 314 | "##### Utilisation d'alias" 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": 26, 320 | "metadata": {}, 321 | "outputs": [ 322 | { 323 | "name": "stdout", 324 | "output_type": "stream", 325 | "text": [ 326 | "3.141592653589793\n" 327 | ] 328 | } 329 | ], 330 | "source": [ 331 | "import math as m\n", 332 | "\n", 333 | "print((m.pi))" 334 | ] 335 | }, 336 | { 337 | "cell_type": "markdown", 338 | "metadata": {}, 339 | "source": [ 340 | "---\n", 341 | "\n", 342 | "## Introduction aux Classes et Objets\n", 343 | "\n", 344 | "### Qu'est-ce que la POO ?\n", 345 | "\n", 346 | "La **Programmation Orientée Objet (POO)** est un paradigme de programmation qui utilise des **objets** et des **classes** pour créer des modèles basés sur le monde réel. Elle facilite :\n", 347 | "\n", 348 | "- **L'organisation du code** : En regroupant les données et les fonctions qui les manipulent.\n", 349 | "- **La réutilisation du code** : Grâce à l'héritage et aux classes génériques.\n", 350 | "- **La maintenance** : En rendant le code plus modulaire et plus facile à comprendre.\n", 351 | "\n", 352 | "### Les Classes\n", 353 | "\n", 354 | "#### Définition d'une classe en programmation\n", 355 | "\n", 356 | "- Une **classe** est un plan ou un modèle qui définit les attributs (données) et les méthodes (comportements) que les objets créés à partir de cette classe posséderont.\n", 357 | "\n", 358 | "#### Syntaxe en Python" 359 | ] 360 | }, 361 | { 362 | "cell_type": "code", 363 | "execution_count": 27, 364 | "metadata": {}, 365 | "outputs": [], 366 | "source": [ 367 | "class NomDeLaClasse:\n", 368 | " # Corps de la classe\n", 369 | " pass\n", 370 | "\n" 371 | ] 372 | }, 373 | { 374 | "cell_type": "markdown", 375 | "metadata": {}, 376 | "source": [ 377 | "- **Convention de nommage** : Les noms de classes sont généralement écrits en **CamelCase**.\n", 378 | "\n", 379 | "##### Exemple :" 380 | ] 381 | }, 382 | { 383 | "cell_type": "code", 384 | "execution_count": 28, 385 | "metadata": {}, 386 | "outputs": [ 387 | { 388 | "name": "stdout", 389 | "output_type": "stream", 390 | "text": [ 391 | "\n" 392 | ] 393 | } 394 | ], 395 | "source": [ 396 | "class Personnage:\n", 397 | " pass\n", 398 | "\n", 399 | "print(Personnage)" 400 | ] 401 | }, 402 | { 403 | "cell_type": "markdown", 404 | "metadata": {}, 405 | "source": [ 406 | "### Les Objets\n", 407 | "\n", 408 | "#### Qu'est-ce qu'un objet ?\n", 409 | "\n", 410 | "- Un **objet** est une instance concrète d'une classe. Il possède ses propres attributs et peut utiliser les méthodes définies par sa classe.\n", 411 | "\n", 412 | "#### Création d'instances\n", 413 | "\n", 414 | "Pour créer une instance d'une classe :\n", 415 | "\n", 416 | "```python\n", 417 | "nom_de_l_instance = NomDeLaClasse()\n", 418 | "```\n", 419 | "##### Exemple :" 420 | ] 421 | }, 422 | { 423 | "cell_type": "code", 424 | "execution_count": 29, 425 | "metadata": {}, 426 | "outputs": [ 427 | { 428 | "name": "stdout", 429 | "output_type": "stream", 430 | "text": [ 431 | "<__main__.Personnage object at 0x1059ba1b0>\n" 432 | ] 433 | } 434 | ], 435 | "source": [ 436 | "class Personnage:\n", 437 | " pass\n", 438 | "\n", 439 | "Zelda = Personnage()\n", 440 | "print(Zelda)" 441 | ] 442 | }, 443 | { 444 | "cell_type": "markdown", 445 | "metadata": {}, 446 | "source": [ 447 | "## Les Méthodes et les Attributs\n", 448 | "\n", 449 | "### Les Attributs de Classe\n", 450 | "\n", 451 | "- **Définition** : Variables partagées par toutes les instances de la classe, définies directement dans la classe.\n", 452 | "- **Utilisation** : Pour des valeurs communes à toutes les instances.\n", 453 | "\n", 454 | "#### Exemple :" 455 | ] 456 | }, 457 | { 458 | "cell_type": "code", 459 | "execution_count": 30, 460 | "metadata": {}, 461 | "outputs": [ 462 | { 463 | "name": "stdout", 464 | "output_type": "stream", 465 | "text": [ 466 | "princesse Hyrule prêtresse\n", 467 | "Zelda est la princesse du royaume d'Hyrule, où elle est prêtresse\n" 468 | ] 469 | } 470 | ], 471 | "source": [ 472 | "class Personnage:\n", 473 | " fonction = \"princesse\"\n", 474 | " royaume = \"Hyrule\"\n", 475 | " pouvoir = \"prêtresse\"\n", 476 | "\n", 477 | "Zelda = Personnage()\n", 478 | "print(Zelda.fonction, Zelda.royaume, Zelda.pouvoir)\n", 479 | "print(f\"Zelda est la {Zelda.fonction} du royaume d'{Zelda.royaume}, où elle est {Zelda.pouvoir}\")" 480 | ] 481 | }, 482 | { 483 | "cell_type": "markdown", 484 | "metadata": {}, 485 | "source": [ 486 | "### Modification d'un attribut de classe \n", 487 | "\n", 488 | "#### Via la classe :\n", 489 | "\n", 490 | "Si vous modifiez un attribut de classe directement via la classe, toutes les instances existantes et futures refléteront ce changement, car elles accèdent à cet attribut à travers la classe." 491 | ] 492 | }, 493 | { 494 | "cell_type": "code", 495 | "execution_count": 31, 496 | "metadata": {}, 497 | "outputs": [ 498 | { 499 | "name": "stdout", 500 | "output_type": "stream", 501 | "text": [ 502 | "New Hyrule\n" 503 | ] 504 | } 505 | ], 506 | "source": [ 507 | "Personnage.royaume = \"New Hyrule\"\n", 508 | "print(Zelda.royaume) # Affiche : New Hyrule" 509 | ] 510 | }, 511 | { 512 | "cell_type": "markdown", 513 | "metadata": {}, 514 | "source": [ 515 | "#### Via une instance :\n", 516 | "\n", 517 | "Si vous modifiez un attribut via une instance, cela ne modifie pas l'attribut de la classe, mais crée un nouvel attribut d'instance pour cette instance uniquement. Les autres instances et la classe conservent leur version de l'attribut de classe." 518 | ] 519 | }, 520 | { 521 | "cell_type": "code", 522 | "execution_count": 32, 523 | "metadata": {}, 524 | "outputs": [ 525 | { 526 | "name": "stdout", 527 | "output_type": "stream", 528 | "text": [ 529 | "sorcière\n", 530 | "prêtresse\n" 531 | ] 532 | } 533 | ], 534 | "source": [ 535 | "Zelda.pouvoir = \"sorcière\"\n", 536 | "print(Zelda.pouvoir) # Affiche : sorcière\n", 537 | "print(Personnage.pouvoir) # Affiche : prêtresse" 538 | ] 539 | }, 540 | { 541 | "cell_type": "markdown", 542 | "metadata": {}, 543 | "source": [ 544 | "### Les Attributs d'Instance\n", 545 | "\n", 546 | "- **Définition** : Variables propres à chaque objet, définies dans la méthode `__init__`.\n", 547 | "- **Création** : Utilisent le mot-clé `self` pour faire référence à l'instance elle-même.\n", 548 | "\n", 549 | "#### Exemple :" 550 | ] 551 | }, 552 | { 553 | "cell_type": "code", 554 | "execution_count": 33, 555 | "metadata": {}, 556 | "outputs": [ 557 | { 558 | "name": "stdout", 559 | "output_type": "stream", 560 | "text": [ 561 | "Zelda Princesse\n" 562 | ] 563 | } 564 | ], 565 | "source": [ 566 | "class Personnage:\n", 567 | " def __init__(self, nom, fonction):\n", 568 | " self.nom = nom\n", 569 | " self.fonction = fonction\n", 570 | "\n", 571 | "Zelda = Personnage(\"Zelda\", \"Princesse\")\n", 572 | "print(Zelda.nom, Zelda.fonction)" 573 | ] 574 | }, 575 | { 576 | "cell_type": "markdown", 577 | "metadata": {}, 578 | "source": [ 579 | "### La Méthode `__init__` et le Paramètre `self`\n", 580 | "\n", 581 | "#### La méthode `__init__`\n", 582 | "\n", 583 | "- **Rôle** : Méthode spéciale appelée **constructeur**, utilisée pour initialiser les attributs d'une instance lors de sa création.\n", 584 | "\n", 585 | "#### Le paramètre `self`\n", 586 | "\n", 587 | "- **Définition** : Représente l'instance de l'objet lui-même.\n", 588 | "- **Utilisation** : Permet d'accéder aux attributs et méthodes de la classe à l'intérieur de ses méthodes.\n", 589 | "\n", 590 | "##### Exemple :" 591 | ] 592 | }, 593 | { 594 | "cell_type": "code", 595 | "execution_count": 34, 596 | "metadata": {}, 597 | "outputs": [ 598 | { 599 | "name": "stdout", 600 | "output_type": "stream", 601 | "text": [ 602 | "Je m'appelle Zelda et je suis Princesse.\n" 603 | ] 604 | } 605 | ], 606 | "source": [ 607 | "class Personnage:\n", 608 | " def __init__(self, nom, fonction):\n", 609 | " self.nom = nom\n", 610 | " self.fonction = fonction\n", 611 | "\n", 612 | " def se_presenter(self):\n", 613 | " print(f\"Je m'appelle {self.nom} et je suis {self.fonction}.\")\n", 614 | "\n", 615 | "Zelda = Personnage(\"Zelda\", \"Princesse\")\n", 616 | "Zelda.se_presenter()" 617 | ] 618 | }, 619 | { 620 | "cell_type": "markdown", 621 | "metadata": {}, 622 | "source": [ 623 | "---\n", 624 | "\n", 625 | "## Exemples Pratiques et Exercices\n", 626 | "\n", 627 | "### Exemple : Classe `Personnage` avec Méthodes et Attributs" 628 | ] 629 | }, 630 | { 631 | "cell_type": "code", 632 | "execution_count": 35, 633 | "metadata": {}, 634 | "outputs": [ 635 | { 636 | "name": "stdout", 637 | "output_type": "stream", 638 | "text": [ 639 | "Zelda est Princesse du royaume d'Hyrule et a le pouvoir de Prêtresse\n", 640 | "Niveau d'expérience : 2\n", 641 | "Link est Élu du royaume d'Hyrule et a le pouvoir de Sauveur du royaume\n", 642 | "Niveau d'expérience : 0\n" 643 | ] 644 | } 645 | ], 646 | "source": [ 647 | "class Personnage:\n", 648 | " def __init__(self, nom, fonction, royaume, pouvoir, xp):\n", 649 | " self.nom = nom\n", 650 | " self.fonction = fonction\n", 651 | " self.royaume = royaume\n", 652 | " self.pouvoir = pouvoir\n", 653 | " self.xp = xp\n", 654 | "\n", 655 | " def gain_xp(self, gxp):\n", 656 | " self.xp += gxp\n", 657 | "\n", 658 | " def infos(self):\n", 659 | " print(f\"{self.nom} est {self.fonction} du royaume d'{self.royaume} et a le pouvoir de {self.pouvoir}\")\n", 660 | " print(f\"Niveau d'expérience : {self.xp}\")\n", 661 | "\n", 662 | "# Création de l'instance Zelda\n", 663 | "Zelda = Personnage(\"Zelda\", \"Princesse\", \"Hyrule\", \"Prêtresse\", 0)\n", 664 | "Zelda.gain_xp(2)\n", 665 | "Zelda.infos()\n", 666 | "\n", 667 | "# Création de l'instance Link\n", 668 | "Link = Personnage(\"Link\", \"Élu\", \"Hyrule\", \"Sauveur du royaume\", 0)\n", 669 | "Link.infos()" 670 | ] 671 | }, 672 | { 673 | "cell_type": "markdown", 674 | "metadata": {}, 675 | "source": [ 676 | "### Exercices\n", 677 | "\n", 678 | "#### Exercice 1 : Ajouter une Méthode `niveau`\n", 679 | "\n", 680 | "**Objectif** : Ajouter une méthode `niveau` à la classe `Personnage` qui détermine le niveau du personnage en fonction de son expérience (`xp`).\n", 681 | "\n", 682 | "- **Niveaux** :\n", 683 | " - `xp` < 5 : Niveau \"Débutant\"\n", 684 | " - 5 <= `xp` < 10 : Niveau \"Intermédiaire\"\n", 685 | " - `xp` >= 10 : Niveau \"Expert\"\n", 686 | "\n", 687 | "**Instructions** :\n", 688 | "\n", 689 | "1. Ajouter la méthode `niveau` à la classe `Personnage`.\n", 690 | "2. Modifier la méthode `infos` pour afficher le niveau du personnage.\n", 691 | "3. Créer un personnage, lui faire gagner de l'expérience, et afficher ses informations.\n" 692 | ] 693 | }, 694 | { 695 | "cell_type": "code", 696 | "execution_count": 36, 697 | "metadata": {}, 698 | "outputs": [], 699 | "source": [ 700 | "# Votre code" 701 | ] 702 | }, 703 | { 704 | "cell_type": "markdown", 705 | "metadata": {}, 706 | "source": [ 707 | "#### Exercice 2 : Créer une Classe `EvenementHistorique`\n", 708 | "\n", 709 | "**Objectif** : Créer une classe `EvenementHistorique` pour modéliser des événements historiques.\n", 710 | "\n", 711 | "**Instructions** :\n", 712 | "\n", 713 | "1. Créer la classe avec les attributs `nom`, `date`, `lieu`, `description`.\n", 714 | "2. Ajouter une méthode `afficher_details` qui affiche toutes les informations de l'événement.\n", 715 | "3. Instancier plusieurs événements et afficher leurs détails." 716 | ] 717 | }, 718 | { 719 | "cell_type": "code", 720 | "execution_count": 37, 721 | "metadata": {}, 722 | "outputs": [], 723 | "source": [ 724 | "# Votre code" 725 | ] 726 | } 727 | ], 728 | "metadata": { 729 | "kernelspec": { 730 | "display_name": "3.12.6", 731 | "language": "python", 732 | "name": "python3" 733 | }, 734 | "language_info": { 735 | "codemirror_mode": { 736 | "name": "ipython", 737 | "version": 3 738 | }, 739 | "file_extension": ".py", 740 | "mimetype": "text/x-python", 741 | "name": "python", 742 | "nbconvert_exporter": "python", 743 | "pygments_lexer": "ipython3", 744 | "version": "3.12.6" 745 | } 746 | }, 747 | "nbformat": 4, 748 | "nbformat_minor": 2 749 | } 750 | -------------------------------------------------------------------------------- /Cours_4_POO_2/Exercices_Séance_4.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Exercices Python - Programmation Orientée Objet et Notions Avancées\n", 8 | "\n", 9 | "Bienvenue dans ce notebook d'exercices qui accompagne le cours sur la Programmation Orientée Objet (POO) et des notions avancées en Python. Ce notebook est conçu pour les étudiants de Master 2 en technologies numériques appliquées à l'histoire. Il vise à vous aider à mettre en pratique les concepts abordés dans le cours à travers des exercices pertinents pour le domaine historique.\n", 10 | "\n", 11 | "---\n", 12 | "\n", 13 | "## Table des Matières\n", 14 | "\n", 15 | "1. [Révisions](#Révisions)\n", 16 | " - [Exercice 1 : Utilisation de `filter()` avec des données historiques](#exercice-1--utilisation-de-filter-avec-des-données-historiques)\n", 17 | " - [Exercice 2 : Typage des paramètres avec des fonctions historiques](#Exercice-2)\n", 18 | " - [Exercice 3 : Gestion des exceptions lors de l'analyse de données](#Exercice-3)\n", 19 | "2. [Introduction aux classes et objets](#Introduction-aux-classes-et-objets)\n", 20 | " - [Exercice 4 : Modélisation de personnages historiques](#Exercice-4)\n", 21 | " - [Exercice 5 : Création d'une classe `ÉvénementHistorique`](#Exercice-5)\n", 22 | "3. [Héritage](#Héritage)\n", 23 | " - [Exercice 6 : Hiérarchie des périodes historiques](#Exercice-6)\n", 24 | " - [Exercice 7 : Spécialisation de la classe `ÉvénementHistorique`](#Exercice-7)\n", 25 | "4. [Les décorateurs](#Les-décorateurs)\n", 26 | " - [Exercice 8 : Création d'un décorateur pour la journalisation](#Exercice-8)\n", 27 | " - [Exercice 9 : Décorateur pour la vérification des données](#Exercice-9)\n", 28 | " - [Exercice 10 : Mesure du temps d'exécution d'une fonction d'analyse](#Exercice-10)\n", 29 | "\n", 30 | "---" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "## Révisions\n", 38 | "\n", 39 | "### Exercice 1 : Utilisation de `filter()` avec des données historiques\n", 40 | "\n", 41 | "**Objectif :**\n", 42 | "\n", 43 | "Utiliser la fonction `filter()` pour extraire des événements historiques se déroulant après une certaine date.\n", 44 | "\n", 45 | "**Instructions :**\n", 46 | "\n", 47 | "1. Vous avez une liste d'événements historiques sous la forme de tuples `(événement, année)`.\n", 48 | "\n", 49 | " ```python\n", 50 | " evenements = [\n", 51 | " (\"Bataille de Marathon\", -490),\n", 52 | " (\"Chute de l'Empire romain d'Occident\", 476),\n", 53 | " (\"Couronnement de Charlemagne\", 800),\n", 54 | " (\"Découverte de l'Amérique\", 1492),\n", 55 | " (\"Révolution française\", 1789),\n", 56 | " (\"Chute du mur de Berlin\", 1989),\n", 57 | " ]\n", 58 | " ```\n", 59 | "\n", 60 | "2. Utilisez `filter()` pour extraire les événements qui se sont produits après l'an 1000.\n", 61 | "\n", 62 | "3. Affichez la liste des événements filtrés.\n", 63 | "\n", 64 | "**Votre code :**" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 1, 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "# Votre code ici" 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": {}, 79 | "source": [ 80 | "### Exercice 2 : Typage des paramètres avec des fonctions historiques\n", 81 | "\n", 82 | "**Objectif :**\n", 83 | "\n", 84 | "Annoter les types des paramètres et des valeurs de retour d'une fonction qui traite des données historiques.\n", 85 | "\n", 86 | "**Instructions :**\n", 87 | "\n", 88 | "1. Créez une fonction `calculer_duree` qui prend deux paramètres : `debut` et `fin`, représentant des années (entiers).\n", 89 | "\n", 90 | "2. La fonction doit retourner la durée entre ces deux années.\n", 91 | "\n", 92 | "3. Ajoutez des annotations de type pour indiquer que les paramètres et la valeur de retour sont des entiers.\n", 93 | "\n", 94 | "4. Testez votre fonction avec les années 1789 et 1799." 95 | ] 96 | }, 97 | { 98 | "cell_type": "code", 99 | "execution_count": 2, 100 | "metadata": {}, 101 | "outputs": [], 102 | "source": [ 103 | "# Votre code ici" 104 | ] 105 | }, 106 | { 107 | "cell_type": "markdown", 108 | "metadata": {}, 109 | "source": [ 110 | "### Exercice 3 : Gestion des exceptions lors de l'analyse de données\n", 111 | "\n", 112 | "**Objectif :**\n", 113 | "\n", 114 | "Gérer les exceptions potentielles lors du traitement de données historiques pour éviter les arrêts brusques du programme.\n", 115 | "\n", 116 | "**Instructions :**\n", 117 | "\n", 118 | "1. Créez une fonction `analyser_population` qui prend en paramètre un dictionnaire représentant la population de villes à différentes époques. Par exemple :\n", 119 | "\n", 120 | " ```python\n", 121 | " populations = {\n", 122 | " \"Babylone\": -500000,\n", 123 | " \"Rome\": 1000000,\n", 124 | " \"Constantinople\": \"un million\",\n", 125 | " \"Paris\": 2240000,\n", 126 | " }\n", 127 | " ```\n", 128 | "\n", 129 | "2. La fonction doit parcourir le dictionnaire et calculer le total de la population.\n", 130 | "\n", 131 | "3. Gérez les exceptions suivantes :\n", 132 | "\n", 133 | " - `ValueError` si la population n'est pas un nombre entier positif.\n", 134 | " - `TypeError` si la valeur n'est pas du bon type.\n", 135 | "\n", 136 | "4. Affichez un message d'erreur approprié pour chaque exception, mais le programme doit continuer à traiter les autres villes.\n", 137 | "\n", 138 | "**Votre code :**" 139 | ] 140 | }, 141 | { 142 | "cell_type": "code", 143 | "execution_count": 3, 144 | "metadata": {}, 145 | "outputs": [], 146 | "source": [ 147 | "# Votre code ici" 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "---\n", 155 | "\n", 156 | "## Introduction aux classes et objets\n", 157 | "\n", 158 | "### Exercice 4 : Modélisation de personnages historiques\n", 159 | "\n", 160 | "**Objectif :**\n", 161 | "\n", 162 | "Créer une classe pour modéliser des personnages historiques avec leurs attributs et méthodes.\n", 163 | "\n", 164 | "**Instructions :**\n", 165 | "\n", 166 | "1. Créez une classe `PersonnageHistorique` avec les attributs :\n", 167 | "\n", 168 | " - `nom`\n", 169 | " - `date_naissance`\n", 170 | " - `date_deces`\n", 171 | " - `nationalite`\n", 172 | "\n", 173 | "2. Ajoutez une méthode `se_presenter` qui affiche une phrase présentant le personnage.\n", 174 | "\n", 175 | "3. Instanciez deux objets de cette classe avec des personnages de votre choix et appelez leur méthode `se_presenter`.\n", 176 | "\n", 177 | "**Votre code :**" 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": 4, 183 | "metadata": {}, 184 | "outputs": [], 185 | "source": [ 186 | "# Votre code ici" 187 | ] 188 | }, 189 | { 190 | "cell_type": "markdown", 191 | "metadata": {}, 192 | "source": [ 193 | "---\n", 194 | "\n", 195 | "### Exercice 5 : Création d'une classe `ÉvénementHistorique`\n", 196 | "\n", 197 | "**Objectif :**\n", 198 | "\n", 199 | "Modéliser des événements historiques en utilisant des attributs de classe et d'instance.\n", 200 | "\n", 201 | "**Instructions :**\n", 202 | "\n", 203 | "1. Créez une classe `EvenementHistorique` avec :\n", 204 | "\n", 205 | " - Un **attribut de classe** `categorie` ayant pour valeur `\"Événement historique\"`.\n", 206 | "\n", 207 | " - Des **attributs d'instance** :\n", 208 | "\n", 209 | " - `nom`\n", 210 | " - `date`\n", 211 | " - `lieu`\n", 212 | "\n", 213 | "2. Ajoutez une méthode `afficher_details` qui affiche les informations de l'événement.\n", 214 | "\n", 215 | "3. Instanciez un objet de cette classe pour l'événement \"Première française de Nosferatu\" le 27 octobre 1922 à Paris, et appelez la méthode `afficher_details`.\n", 216 | "\n", 217 | "**Votre code :**" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": 5, 223 | "metadata": {}, 224 | "outputs": [], 225 | "source": [ 226 | "# Votre code ici" 227 | ] 228 | }, 229 | { 230 | "cell_type": "markdown", 231 | "metadata": {}, 232 | "source": [ 233 | "## Héritage\n", 234 | "\n", 235 | "### Exercice 6 : Hiérarchie des périodes historiques\n", 236 | "\n", 237 | "**Objectif :**\n", 238 | "\n", 239 | "Utiliser l'héritage pour modéliser les périodes historiques.\n", 240 | "\n", 241 | "**Instructions :**\n", 242 | "\n", 243 | "1. Créez une classe de base `PeriodeHistorique` avec les attributs :\n", 244 | "\n", 245 | " - `nom`\n", 246 | " - `debut` (année de début)\n", 247 | " - `fin` (année de fin)\n", 248 | "\n", 249 | "2. Créez des classes enfants qui héritent de `PeriodeHistorique` :\n", 250 | "\n", 251 | " - `Antiquite`\n", 252 | " - `MoyenAge`\n", 253 | " - `EpoqueModerne`\n", 254 | "\n", 255 | "3. Ajoutez une méthode `duree` dans la classe de base qui calcule la durée de la période.\n", 256 | "\n", 257 | "4. Instanciez un objet de chaque classe enfant avec les dates correspondantes et affichez la durée de chaque période.\n", 258 | "\n", 259 | "**Votre code :**" 260 | ] 261 | }, 262 | { 263 | "cell_type": "code", 264 | "execution_count": 6, 265 | "metadata": {}, 266 | "outputs": [], 267 | "source": [ 268 | "# Votre code ici" 269 | ] 270 | }, 271 | { 272 | "cell_type": "markdown", 273 | "metadata": {}, 274 | "source": [ 275 | "---\n", 276 | "\n", 277 | "### Exercice 7 : Spécialisation de la classe `EvenementHistorique`\n", 278 | "\n", 279 | "**Objectif :**\n", 280 | "\n", 281 | "Créer des classes spécialisées en héritant de `EvenementHistorique`, centrées sur des **découvertes**.\n", 282 | "\n", 283 | "**Instructions :**\n", 284 | "\n", 285 | "1. À partir de la classe `EvenementHistorique` de l'Exercice 5, créez deux classes enfants :\n", 286 | "\n", 287 | " - `DecouverteScientifique` : ajoute l'attribut `decouvreur` (nom du ou des scientifiques impliqués).\n", 288 | " - `ExplorationGeographique` : ajoute l'attribut `explorateurs` (liste des explorateurs impliqués).\n", 289 | "\n", 290 | "2. Ajoutez une méthode spécifique à chaque classe enfant :\n", 291 | "\n", 292 | " - Pour `DecouverteScientifique`, une méthode `decrire_decouverte` qui décrit la découverte scientifique.\n", 293 | " - Pour `ExplorationGeographique`, une méthode `decrire_exploration` qui décrit l'exploration géographique.\n", 294 | "\n", 295 | "3. Instanciez un objet de chaque classe :\n", 296 | "\n", 297 | " - Une découverte scientifique de votre choix.\n", 298 | " - Une exploration géographique de votre choix.\n", 299 | "\n", 300 | "4. Appelez les méthodes pour afficher les informations spécifiques.\n", 301 | "\n", 302 | "**Votre code :**\n", 303 | "\n" 304 | ] 305 | }, 306 | { 307 | "cell_type": "code", 308 | "execution_count": 7, 309 | "metadata": {}, 310 | "outputs": [], 311 | "source": [ 312 | "# Votre code ici" 313 | ] 314 | }, 315 | { 316 | "cell_type": "markdown", 317 | "metadata": {}, 318 | "source": [ 319 | "---\n", 320 | "\n", 321 | "## Les décorateurs\n", 322 | "\n", 323 | "### Exercice 8 : Création d'un décorateur pour la journalisation\n", 324 | "\n", 325 | "**Objectif :**\n", 326 | "\n", 327 | "Créer un décorateur qui journalise les appels de fonctions d'analyse historique.\n", 328 | "\n", 329 | "**Instructions :**\n", 330 | "\n", 331 | "1. Créez un décorateur `journaliser_appel` qui :\n", 332 | "\n", 333 | " - Affiche un message avant et après l'appel de la fonction, indiquant le nom de la fonction.\n", 334 | "\n", 335 | "2. Appliquez ce décorateur à une fonction `analyser_texte` qui prend un texte (chaîne de caractères) et affiche \"Analyse en cours...\".\n", 336 | "\n", 337 | "3. Testez la fonction en l'appelant avec un texte quelconque.\n", 338 | "\n", 339 | "**Votre code :**" 340 | ] 341 | }, 342 | { 343 | "cell_type": "code", 344 | "execution_count": 8, 345 | "metadata": {}, 346 | "outputs": [], 347 | "source": [ 348 | "# Votre code ici :" 349 | ] 350 | }, 351 | { 352 | "cell_type": "markdown", 353 | "metadata": {}, 354 | "source": [ 355 | "---\n", 356 | "\n", 357 | "### Exercice 9 : Décorateur pour la vérification des données\n", 358 | "\n", 359 | "**Objectif :**\n", 360 | "\n", 361 | "Utiliser les décorateurs pour vérifier les données passées à une fonction.\n", 362 | "\n", 363 | "**Instructions :**\n", 364 | "\n", 365 | "1. Créez un décorateur `verifier_annee` qui :\n", 366 | "\n", 367 | " - Vérifie que l'argument `annee` passé à la fonction est un entier positif.\n", 368 | " - Si ce n'est pas le cas, lève une exception `ValueError` avec un message approprié.\n", 369 | "\n", 370 | "2. Appliquez ce décorateur à une fonction `afficher_evenements_annee` qui affiche les événements d'une année donnée.\n", 371 | "\n", 372 | "3. Testez la fonction avec une année valide et une année invalide (par exemple, une chaîne de caractères ou un entier négatif).\n", 373 | "\n", 374 | "**Votre code :**" 375 | ] 376 | }, 377 | { 378 | "cell_type": "code", 379 | "execution_count": 9, 380 | "metadata": {}, 381 | "outputs": [], 382 | "source": [ 383 | "# Votre code ici" 384 | ] 385 | }, 386 | { 387 | "cell_type": "markdown", 388 | "metadata": {}, 389 | "source": [ 390 | "---\n", 391 | "\n", 392 | "\n", 393 | "### Exercice 10 : Mesure du temps d'exécution d'une fonction d'analyse\n", 394 | "\n", 395 | "**Objectif :**\n", 396 | "\n", 397 | "Créer un décorateur qui mesure le temps d'exécution d'une fonction.\n", 398 | "\n", 399 | "**Instructions :**\n", 400 | "\n", 401 | "1. Créez un décorateur `mesurer_temps_execution` qui :\n", 402 | "\n", 403 | " - Mesure le temps pris par la fonction pour s'exécuter.\n", 404 | " - Affiche le temps d'exécution avec le nom de la fonction.\n", 405 | "\n", 406 | "2. Appliquez ce décorateur à une fonction `traiter_donnees_historique` qui simule un traitement long (par exemple, en utilisant `time.sleep(2)`).\n", 407 | "\n", 408 | "3. Testez la fonction et vérifiez que le temps d'exécution est affiché.\n", 409 | "\n", 410 | "**Votre code :**" 411 | ] 412 | }, 413 | { 414 | "cell_type": "code", 415 | "execution_count": 10, 416 | "metadata": {}, 417 | "outputs": [], 418 | "source": [ 419 | "# Votre code ici" 420 | ] 421 | } 422 | ], 423 | "metadata": { 424 | "kernelspec": { 425 | "display_name": "3.12.6", 426 | "language": "python", 427 | "name": "python3" 428 | }, 429 | "language_info": { 430 | "codemirror_mode": { 431 | "name": "ipython", 432 | "version": 3 433 | }, 434 | "file_extension": ".py", 435 | "mimetype": "text/x-python", 436 | "name": "python", 437 | "nbconvert_exporter": "python", 438 | "pygments_lexer": "ipython3", 439 | "version": "3.12.6" 440 | } 441 | }, 442 | "nbformat": 4, 443 | "nbformat_minor": 2 444 | } 445 | -------------------------------------------------------------------------------- /Cours_4_POO_2/Exercices_Séance_4_correction.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Exercices Python - Programmation Orientée Objet et Notions Avancées\n", 8 | "\n", 9 | "Bienvenue dans ce notebook d'exercices qui accompagne le cours sur la Programmation Orientée Objet (POO) et des notions avancées en Python. Ce notebook est conçu pour les étudiants de Master 2 en technologies numériques appliquées à l'histoire. Il vise à vous aider à mettre en pratique les concepts abordés dans le cours à travers des exercices pertinents pour le domaine historique.\n", 10 | "\n", 11 | "---\n", 12 | "\n", 13 | "## Table des Matières\n", 14 | "\n", 15 | "1. [Révisions](#Révisions)\n", 16 | " - [Exercice 1 : Utilisation de `filter()` avec des données historiques](#exercice-1--utilisation-de-filter-avec-des-données-historiques)\n", 17 | " - [Exercice 2 : Typage des paramètres avec des fonctions historiques](#Exercice-2)\n", 18 | " - [Exercice 3 : Gestion des exceptions lors de l'analyse de données](#Exercice-3)\n", 19 | "2. [Introduction aux classes et objets](#Introduction-aux-classes-et-objets)\n", 20 | " - [Exercice 4 : Modélisation de personnages historiques](#Exercice-4)\n", 21 | " - [Exercice 5 : Création d'une classe `ÉvénementHistorique`](#Exercice-5)\n", 22 | "3. [Héritage](#Héritage)\n", 23 | " - [Exercice 6 : Hiérarchie des périodes historiques](#Exercice-6)\n", 24 | " - [Exercice 7 : Spécialisation de la classe `ÉvénementHistorique`](#Exercice-7)\n", 25 | "4. [Les décorateurs](#Les-décorateurs)\n", 26 | " - [Exercice 8 : Création d'un décorateur pour la journalisation](#Exercice-8)\n", 27 | " - [Exercice 9 : Décorateur pour la vérification des données](#Exercice-9)\n", 28 | " - [Exercice 10 : Mesure du temps d'exécution d'une fonction d'analyse](#Exercice-10)\n", 29 | "\n", 30 | "---" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "## Révisions\n", 38 | "\n", 39 | "### Exercice 1 : Utilisation de `filter()` avec des données historiques\n", 40 | "\n", 41 | "**Objectif :**\n", 42 | "\n", 43 | "Utiliser la fonction `filter()` pour extraire des événements historiques se déroulant après une certaine date.\n", 44 | "\n", 45 | "**Instructions :**\n", 46 | "\n", 47 | "1. Vous avez une liste d'événements historiques sous la forme de tuples `(événement, année)`.\n", 48 | "\n", 49 | " ```python\n", 50 | " evenements = [\n", 51 | " (\"Bataille de Marathon\", -490),\n", 52 | " (\"Chute de l'Empire romain d'Occident\", 476),\n", 53 | " (\"Couronnement de Charlemagne\", 800),\n", 54 | " (\"Découverte de l'Amérique\", 1492),\n", 55 | " (\"Révolution française\", 1789),\n", 56 | " (\"Chute du mur de Berlin\", 1989),\n", 57 | " ]\n", 58 | " ```\n", 59 | "\n", 60 | "2. Utilisez `filter()` pour extraire les événements qui se sont produits après l'an 1000.\n", 61 | "\n", 62 | "3. Affichez la liste des événements filtrés.\n", 63 | "\n", 64 | "**Votre code :**" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 20, 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "# Votre code ici" 74 | ] 75 | }, 76 | { 77 | "cell_type": "markdown", 78 | "metadata": {}, 79 | "source": [ 80 | "
\n", 81 | "Solution Exercice 1 \n", 82 | "\n", 83 | "```python\n", 84 | "evenements = [\n", 85 | " (\"Bataille de Marathon\", -490),\n", 86 | " (\"Chute de l'Empire romain d'Occident\", 476),\n", 87 | " (\"Couronnement de Charlemagne\", 800),\n", 88 | " (\"Découverte de l'Amérique\", 1492),\n", 89 | " (\"Révolution française\", 1789),\n", 90 | " (\"Chute du mur de Berlin\", 1989),\n", 91 | "]\n", 92 | "\n", 93 | "# Utilisation de filter pour extraire les événements après l'an 1000\n", 94 | "evenements_apres_1000 = list(filter(lambda e: e[1] > 1000, evenements))\n", 95 | "\n", 96 | "print(\"Événements après l'an 1000 :\")\n", 97 | "for evenement in evenements_apres_1000:\n", 98 | " print(f\"- {evenement[0]} ({evenement[1]})\")\n", 99 | "```\n", 100 | "\n", 101 | "---" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "### Exercice 2 : Typage des paramètres avec des fonctions historiques\n", 109 | "\n", 110 | "**Objectif :**\n", 111 | "\n", 112 | "Annoter les types des paramètres et des valeurs de retour d'une fonction qui traite des données historiques.\n", 113 | "\n", 114 | "**Instructions :**\n", 115 | "\n", 116 | "1. Créez une fonction `calculer_duree` qui prend deux paramètres : `debut` et `fin`, représentant des années (entiers).\n", 117 | "\n", 118 | "2. La fonction doit retourner la durée entre ces deux années.\n", 119 | "\n", 120 | "3. Ajoutez des annotations de type pour indiquer que les paramètres et la valeur de retour sont des entiers.\n", 121 | "\n", 122 | "4. Testez votre fonction avec les années 1789 et 1799." 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 21, 128 | "metadata": {}, 129 | "outputs": [], 130 | "source": [ 131 | "# Votre code ici" 132 | ] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "metadata": {}, 137 | "source": [ 138 | "
\n", 139 | "Solution Exercice 2 \n", 140 | "\n", 141 | "```python\n", 142 | "def calculer_duree(debut: int, fin: int) -> int:\n", 143 | " return fin - debut\n", 144 | "\n", 145 | "duree = calculer_duree(1789, 1799)\n", 146 | "print(f\"La durée est de {duree} ans.\")\n", 147 | "```\n", 148 | "\n", 149 | "---" 150 | ] 151 | }, 152 | { 153 | "cell_type": "markdown", 154 | "metadata": {}, 155 | "source": [ 156 | "### Exercice 3 : Gestion des exceptions lors de l'analyse de données\n", 157 | "\n", 158 | "**Objectif :**\n", 159 | "\n", 160 | "Gérer les exceptions potentielles lors du traitement de données historiques pour éviter les arrêts brusques du programme.\n", 161 | "\n", 162 | "**Instructions :**\n", 163 | "\n", 164 | "1. Créez une fonction `analyser_population` qui prend en paramètre un dictionnaire représentant la population de villes à différentes époques. Par exemple :\n", 165 | "\n", 166 | " ```python\n", 167 | " populations = {\n", 168 | " \"Babylone\": -500000,\n", 169 | " \"Rome\": 1000000,\n", 170 | " \"Constantinople\": \"un million\",\n", 171 | " \"Paris\": 2240000,\n", 172 | " }\n", 173 | " ```\n", 174 | "\n", 175 | "2. La fonction doit parcourir le dictionnaire et calculer le total de la population.\n", 176 | "\n", 177 | "3. Gérez les exceptions suivantes :\n", 178 | "\n", 179 | " - `ValueError` si la population n'est pas un nombre entier positif.\n", 180 | " - `TypeError` si la valeur n'est pas du bon type.\n", 181 | "\n", 182 | "4. Affichez un message d'erreur approprié pour chaque exception, mais le programme doit continuer à traiter les autres villes.\n", 183 | "\n", 184 | "**Votre code :**" 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": 30, 190 | "metadata": {}, 191 | "outputs": [], 192 | "source": [ 193 | "# Votre code ici" 194 | ] 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "metadata": {}, 199 | "source": [ 200 | "
\n", 201 | "Solution Exercice 3 \n", 202 | "\n", 203 | "```python\n", 204 | "def analyser_population(populations:dict) -> str:\n", 205 | " total = 0\n", 206 | " for ville, population in populations.items():\n", 207 | " try:\n", 208 | " if not isinstance(population, int):\n", 209 | " raise TypeError(f\"La population de {ville} n'est pas un entier.\")\n", 210 | " if population < 0:\n", 211 | " raise ValueError(f\"La population de {ville} ne peut pas être négative.\")\n", 212 | " total += population\n", 213 | " except (ValueError, TypeError) as e:\n", 214 | " print(f\"Erreur pour {ville} : {e}\")\n", 215 | " continue\n", 216 | " print(f\"Population totale : {total}\")\n", 217 | "\n", 218 | "pomme = {\n", 219 | " \"Babylone\": -500000,\n", 220 | " \"Rome\": 1000000,\n", 221 | " \"Constantinople\": \"un million\",\n", 222 | " \"Paris\": 2240000,\n", 223 | "}\n", 224 | "\n", 225 | "analyser_population(pomme)\n", 226 | "```\n", 227 | "\n", 228 | "---" 229 | ] 230 | }, 231 | { 232 | "cell_type": "markdown", 233 | "metadata": {}, 234 | "source": [ 235 | "---\n", 236 | "\n", 237 | "## Introduction aux classes et objets\n", 238 | "\n", 239 | "### Exercice 4 : Modélisation de personnages historiques\n", 240 | "\n", 241 | "**Objectif :**\n", 242 | "\n", 243 | "Créer une classe pour modéliser des personnages historiques avec leurs attributs et méthodes.\n", 244 | "\n", 245 | "**Instructions :**\n", 246 | "\n", 247 | "1. Créez une classe `PersonnageHistorique` avec les attributs :\n", 248 | "\n", 249 | " - `nom`\n", 250 | " - `date_naissance`\n", 251 | " - `date_deces`\n", 252 | " - `nationalite`\n", 253 | "\n", 254 | "2. Ajoutez une méthode `se_presenter` qui affiche une phrase présentant le personnage.\n", 255 | "\n", 256 | "3. Instanciez deux objets de cette classe avec des personnages de votre choix et appelez leur méthode `se_presenter`.\n", 257 | "\n", 258 | "**Votre code :**" 259 | ] 260 | }, 261 | { 262 | "cell_type": "code", 263 | "execution_count": 23, 264 | "metadata": {}, 265 | "outputs": [], 266 | "source": [ 267 | "# Votre code ici" 268 | ] 269 | }, 270 | { 271 | "cell_type": "markdown", 272 | "metadata": {}, 273 | "source": [ 274 | "
\n", 275 | "Solution Exercice 4 \n", 276 | "\n", 277 | "```python\n", 278 | "class PersonnageHistorique:\n", 279 | " def __init__(self, nom, date_naissance, date_deces, nationalite):\n", 280 | " self.nom = nom\n", 281 | " self.date_naissance = date_naissance\n", 282 | " self.date_deces = date_deces\n", 283 | " self.nationalite = nationalite\n", 284 | "\n", 285 | " def se_presenter(self):\n", 286 | " print(f\"Je suis {self.nom} ({self.nationalite}), né(e) en {self.date_naissance} et décédé(e) en {self.date_deces}.\")\n", 287 | "\n", 288 | "# Instanciation\n", 289 | "darwin = PersonnageHistorique(\"Charles Darwin\", 1809, 1882, \"Britannique\")\n", 290 | "cleopatre = PersonnageHistorique(\"Cléopâtre VII\", -69, -30, \"Égyptienne\")\n", 291 | "\n", 292 | "darwin.se_presenter()\n", 293 | "cleopatre.se_presenter()\n", 294 | "```\n", 295 | "\n", 296 | "---" 297 | ] 298 | }, 299 | { 300 | "cell_type": "markdown", 301 | "metadata": {}, 302 | "source": [ 303 | "---\n", 304 | "\n", 305 | "### Exercice 5 : Création d'une classe `ÉvénementHistorique`\n", 306 | "\n", 307 | "**Objectif :**\n", 308 | "\n", 309 | "Modéliser des événements historiques en utilisant des attributs de classe et d'instance.\n", 310 | "\n", 311 | "**Instructions :**\n", 312 | "\n", 313 | "1. Créez une classe `EvenementHistorique` avec :\n", 314 | "\n", 315 | " - Un **attribut de classe** `categorie` ayant pour valeur `\"Événement historique\"`.\n", 316 | "\n", 317 | " - Des **attributs d'instance** :\n", 318 | "\n", 319 | " - `nom`\n", 320 | " - `date`\n", 321 | " - `lieu`\n", 322 | "\n", 323 | "2. Ajoutez une méthode `afficher_details` qui affiche les informations de l'événement.\n", 324 | "\n", 325 | "3. Instanciez un objet de cette classe pour l'événement \"Première française de Nosferatu\" le 27 octobre 1922 à Paris, et appelez la méthode `afficher_details`.\n", 326 | "\n", 327 | "**Votre code :**" 328 | ] 329 | }, 330 | { 331 | "cell_type": "code", 332 | "execution_count": 24, 333 | "metadata": {}, 334 | "outputs": [], 335 | "source": [ 336 | "# Votre code ici" 337 | ] 338 | }, 339 | { 340 | "cell_type": "markdown", 341 | "metadata": {}, 342 | "source": [ 343 | "
\n", 344 | "Solution Exercice 5 \n", 345 | "\n", 346 | "```python\n", 347 | "class EvenementHistorique:\n", 348 | " categorie = \"Événement historique\"\n", 349 | "\n", 350 | " def __init__(self, nom, date, lieu):\n", 351 | " self.nom = nom\n", 352 | " self.date = date\n", 353 | " self.lieu = lieu\n", 354 | "\n", 355 | " def afficher_details(self):\n", 356 | " print(f\"{self.nom} ({self.date}) à {self.lieu} - Catégorie : {self.categorie}\")\n", 357 | "\n", 358 | "# Instanciation\n", 359 | "prise_bastille = EvenementHistorique(\"Première française de Nosferatu\", \"27 octobre 1922\", \"Paris\")\n", 360 | "prise_bastille.afficher_details()\n", 361 | "```\n", 362 | "\n", 363 | "---" 364 | ] 365 | }, 366 | { 367 | "cell_type": "markdown", 368 | "metadata": {}, 369 | "source": [ 370 | "## Héritage\n", 371 | "\n", 372 | "### Exercice 6 : Hiérarchie des périodes historiques\n", 373 | "\n", 374 | "**Objectif :**\n", 375 | "\n", 376 | "Utiliser l'héritage pour modéliser les périodes historiques.\n", 377 | "\n", 378 | "**Instructions :**\n", 379 | "\n", 380 | "1. Créez une classe de base `PeriodeHistorique` avec les attributs :\n", 381 | "\n", 382 | " - `nom`\n", 383 | " - `debut` (année de début)\n", 384 | " - `fin` (année de fin)\n", 385 | "\n", 386 | "2. Créez des classes enfants qui héritent de `PeriodeHistorique` :\n", 387 | "\n", 388 | " - `Antiquite`\n", 389 | " - `MoyenAge`\n", 390 | " - `EpoqueModerne`\n", 391 | "\n", 392 | "3. Ajoutez une méthode `duree` dans la classe de base qui calcule la durée de la période.\n", 393 | "\n", 394 | "4. Instanciez un objet de chaque classe enfant avec les dates correspondantes et affichez la durée de chaque période.\n", 395 | "\n", 396 | "**Votre code :**" 397 | ] 398 | }, 399 | { 400 | "cell_type": "code", 401 | "execution_count": 25, 402 | "metadata": {}, 403 | "outputs": [], 404 | "source": [ 405 | "# Votre code ici" 406 | ] 407 | }, 408 | { 409 | "cell_type": "markdown", 410 | "metadata": {}, 411 | "source": [ 412 | "
\n", 413 | "Solution Exercice 6 \n", 414 | "\n", 415 | "```python\n", 416 | "class PeriodeHistorique:\n", 417 | " def __init__(self, nom, debut, fin):\n", 418 | " self.nom = nom\n", 419 | " self.debut = debut\n", 420 | " self.fin = fin\n", 421 | "\n", 422 | " def duree(self):\n", 423 | " return self.fin - self.debut\n", 424 | "\n", 425 | "class Antiquite(PeriodeHistorique):\n", 426 | " def __init__(self, nom, debut, fin, aire_geographique):\n", 427 | " super().__init__(nom, debut, fin)\n", 428 | " self.aire_geographique = aire_geographique\n", 429 | "\n", 430 | " def presentation(self):\n", 431 | " print(f\"La période {self.nom} a duré {self.duree()} et s'est déroulé {self.aire_geographique}\")\n", 432 | "\n", 433 | "class MoyenAge(PeriodeHistorique):\n", 434 | " def __init__(self, nom, debut, fin, chateau):\n", 435 | " super().__init__(nom, debut, fin)\n", 436 | " self.chateau = chateau\n", 437 | "\n", 438 | " def presentation(self):\n", 439 | " print(f\"La période {self.nom} a duré {self.duree()} et le chateau le plus connu est {self.chateau}\")\n", 440 | "\n", 441 | "class EpoqueModerne(PeriodeHistorique):\n", 442 | " def __init__(self, nom, debut, fin, invention):\n", 443 | " super().__init__(nom, debut, fin)\n", 444 | " self.invention = invention\n", 445 | " def presentation(self):\n", 446 | " print(f\"La période {self.nom} a duré {self.duree()} et mon invention majeure est {self.invention}\")\n", 447 | "\n", 448 | "# Instanciations\n", 449 | "antiquite = Antiquite(\"Dynastie archaïque\", -2900, -2340, \"Sumer\")\n", 450 | "moyen_age = MoyenAge(\"Moyen Âge\", 476, 1492, \"Le Louvre\")\n", 451 | "epoque_moderne = EpoqueModerne(\"Époque moderne\", 1492, 1789, \"imprimerie\")\n", 452 | "\n", 453 | "# Affichage les détails\n", 454 | "antiquite.presentation()\n", 455 | "moyen_age.presentation()\n", 456 | "epoque_moderne.presentation()\n", 457 | "```\n", 458 | "\n", 459 | "---" 460 | ] 461 | }, 462 | { 463 | "cell_type": "markdown", 464 | "metadata": {}, 465 | "source": [ 466 | "---\n", 467 | "\n", 468 | "### Exercice 7 : Spécialisation de la classe `EvenementHistorique`\n", 469 | "\n", 470 | "**Objectif :**\n", 471 | "\n", 472 | "Créer des classes spécialisées en héritant de `EvenementHistorique`, centrées sur des **découvertes**.\n", 473 | "\n", 474 | "**Instructions :**\n", 475 | "\n", 476 | "1. À partir de la classe `EvenementHistorique` de l'Exercice 5, créez deux classes enfants :\n", 477 | "\n", 478 | " - `DecouverteScientifique` : ajoute l'attribut `decouvreur` (nom du ou des scientifiques impliqués).\n", 479 | " - `ExplorationGeographique` : ajoute l'attribut `explorateurs` (liste des explorateurs impliqués).\n", 480 | "\n", 481 | "2. Ajoutez une méthode spécifique à chaque classe enfant :\n", 482 | "\n", 483 | " - Pour `DecouverteScientifique`, une méthode `decrire_decouverte` qui décrit la découverte scientifique.\n", 484 | " - Pour `ExplorationGeographique`, une méthode `decrire_exploration` qui décrit l'exploration géographique.\n", 485 | "\n", 486 | "3. Instanciez un objet de chaque classe :\n", 487 | "\n", 488 | " - Une découverte scientifique de votre choix.\n", 489 | " - Une exploration géographique de votre choix.\n", 490 | "\n", 491 | "4. Appelez les méthodes pour afficher les informations spécifiques.\n", 492 | "\n", 493 | "**Votre code :**\n", 494 | "\n" 495 | ] 496 | }, 497 | { 498 | "cell_type": "code", 499 | "execution_count": 26, 500 | "metadata": {}, 501 | "outputs": [], 502 | "source": [ 503 | "# Votre code ici" 504 | ] 505 | }, 506 | { 507 | "cell_type": "markdown", 508 | "metadata": {}, 509 | "source": [ 510 | "
\n", 511 | "Solution Exercice 7 \n", 512 | "\n", 513 | "\n", 514 | "```python\n", 515 | "# Classe parente\n", 516 | "class EvenementHistorique:\n", 517 | " def __init__(self, titre, date, lieu):\n", 518 | " self.titre = titre\n", 519 | " self.date = date\n", 520 | " self.lieu = lieu\n", 521 | "\n", 522 | " def afficher_details(self):\n", 523 | " print(f\"Titre : {self.titre}\")\n", 524 | " print(f\"Date : {self.date}\")\n", 525 | " print(f\"Lieu : {self.lieu}\")\n", 526 | "\n", 527 | "# Classe enfant pour les découvertes scientifiques\n", 528 | "class DecouverteScientifique(EvenementHistorique):\n", 529 | " def __init__(self, titre, date, lieu, decouvreur):\n", 530 | " super().__init__(titre, date, lieu)\n", 531 | " self.decouvreur = decouvreur\n", 532 | "\n", 533 | " def decrire_decouverte(self):\n", 534 | " self.afficher_details()\n", 535 | " print(f\"Découverte réalisée par : {self.decouvreur}\")\n", 536 | "\n", 537 | "# Classe enfant pour les explorations géographiques\n", 538 | "class ExplorationGeographique(EvenementHistorique):\n", 539 | " def __init__(self, titre, date, lieu, explorateurs):\n", 540 | " super().__init__(titre, date, lieu)\n", 541 | " self.explorateurs = explorateurs\n", 542 | "\n", 543 | " def decrire_exploration(self):\n", 544 | " self.afficher_details()\n", 545 | " print(f\"Explorateurs impliqués : {', '.join(self.explorateurs)}\")\n", 546 | "\n", 547 | "# Instanciation d'une découverte scientifique\n", 548 | "decouverte_penicilline = DecouverteScientifique(\n", 549 | " \"Découverte de la pénicilline\",\n", 550 | " \"1928\",\n", 551 | " \"Londres\",\n", 552 | " \"Alexander Fleming\"\n", 553 | ")\n", 554 | "\n", 555 | "# Instanciation d'une exploration géographique\n", 556 | "premier_pas_lune = ExplorationGeographique(\n", 557 | " \"Premier pas sur la Lune\",\n", 558 | " \"1969\",\n", 559 | " \"Lune\",\n", 560 | " [\"Neil Armstrong\", \"Buzz Aldrin\", \"Michael Collins\"]\n", 561 | ")\n", 562 | "\n", 563 | "# Appel des méthodes pour afficher les informations spécifiques\n", 564 | "print(\"=== Découverte Scientifique ===\")\n", 565 | "decouverte_penicilline.decrire_decouverte()\n", 566 | "\n", 567 | "print(\"\\n=== Exploration Géographique ===\")\n", 568 | "premier_pas_lune.decrire_exploration()\n", 569 | "```\n", 570 | "\n", 571 | "---" 572 | ] 573 | }, 574 | { 575 | "cell_type": "markdown", 576 | "metadata": {}, 577 | "source": [ 578 | "---\n", 579 | "\n", 580 | "## Les décorateurs\n", 581 | "\n", 582 | "### Exercice 8 : Création d'un décorateur pour la journalisation\n", 583 | "\n", 584 | "**Objectif :**\n", 585 | "\n", 586 | "Créer un décorateur qui journalise les appels de fonctions d'analyse historique.\n", 587 | "\n", 588 | "**Instructions :**\n", 589 | "\n", 590 | "1. Créez un décorateur `journaliser_appel` qui :\n", 591 | "\n", 592 | " - Affiche un message avant et après l'appel de la fonction, indiquant le nom de la fonction.\n", 593 | "\n", 594 | "2. Appliquez ce décorateur à une fonction `analyser_texte` qui prend un texte (chaîne de caractères) et affiche \"Analyse en cours...\".\n", 595 | "\n", 596 | "3. Testez la fonction en l'appelant avec un texte quelconque.\n", 597 | "\n", 598 | "**Votre code :**" 599 | ] 600 | }, 601 | { 602 | "cell_type": "code", 603 | "execution_count": 27, 604 | "metadata": {}, 605 | "outputs": [], 606 | "source": [ 607 | "# Votre code ici" 608 | ] 609 | }, 610 | { 611 | "cell_type": "markdown", 612 | "metadata": {}, 613 | "source": [ 614 | "
\n", 615 | "Solution Exercice 8 \n", 616 | "\n", 617 | "```python\n", 618 | "def journaliser_appel(fonction):\n", 619 | " def wrapper(*args, **kwargs):\n", 620 | " print(f\"Appel de la fonction '{fonction.__name__}'\")\n", 621 | " resultat = fonction(*args, **kwargs)\n", 622 | " print(f\"Fin de la fonction '{fonction.__name__}'\")\n", 623 | " return resultat\n", 624 | " return wrapper\n", 625 | "\n", 626 | "@journaliser_appel\n", 627 | "def analyser_texte(texte):\n", 628 | " print(\"Analyse en cours...\")\n", 629 | " # Simulation d'une analyse\n", 630 | " return True\n", 631 | "\n", 632 | "# Test\n", 633 | "analyser_texte(\"Ceci est un texte historique.\")\n", 634 | "```\n", 635 | "\n", 636 | "---" 637 | ] 638 | }, 639 | { 640 | "cell_type": "markdown", 641 | "metadata": {}, 642 | "source": [ 643 | "---\n", 644 | "\n", 645 | "### Exercice 9 : Décorateur pour la vérification des données\n", 646 | "\n", 647 | "**Objectif :**\n", 648 | "\n", 649 | "Utiliser les décorateurs pour vérifier les données passées à une fonction.\n", 650 | "\n", 651 | "**Instructions :**\n", 652 | "\n", 653 | "1. Créez un décorateur `verifier_annee` qui :\n", 654 | "\n", 655 | " - Vérifie que l'argument `annee` passé à la fonction est un entier positif.\n", 656 | " - Si ce n'est pas le cas, lève une exception `ValueError` avec un message approprié.\n", 657 | "\n", 658 | "2. Appliquez ce décorateur à une fonction `afficher_evenements_annee` qui affiche les événements d'une année donnée.\n", 659 | "\n", 660 | "3. Testez la fonction avec une année valide et une année invalide (par exemple, une chaîne de caractères ou un entier négatif).\n", 661 | "\n", 662 | "**Votre code :**" 663 | ] 664 | }, 665 | { 666 | "cell_type": "code", 667 | "execution_count": 28, 668 | "metadata": {}, 669 | "outputs": [], 670 | "source": [ 671 | "# Votre code ici" 672 | ] 673 | }, 674 | { 675 | "cell_type": "markdown", 676 | "metadata": {}, 677 | "source": [ 678 | "
\n", 679 | "Solution Exercice 9 \n", 680 | "\n", 681 | "```python\n", 682 | "def verifier_annee(fonction):\n", 683 | " def wrapper(annee, *args, **kwargs):\n", 684 | " if not isinstance(annee, int) or annee <= 0:\n", 685 | " raise ValueError(\"L'année doit être un entier positif.\")\n", 686 | " return fonction(annee, *args, **kwargs)\n", 687 | " return wrapper\n", 688 | "\n", 689 | "@verifier_annee\n", 690 | "def afficher_evenements_annee(annee):\n", 691 | " print(f\"Affichage des événements pour l'année {annee}.\")\n", 692 | "\n", 693 | "# Test avec une année valide\n", 694 | "afficher_evenements_annee(1789)\n", 695 | "\n", 696 | "# Test avec une année invalide\n", 697 | "try:\n", 698 | " afficher_evenements_annee(\"mille\")\n", 699 | "except ValueError as e:\n", 700 | " print(f\"Erreur : {e}\")\n", 701 | "```\n", 702 | "\n", 703 | "---" 704 | ] 705 | }, 706 | { 707 | "cell_type": "markdown", 708 | "metadata": {}, 709 | "source": [ 710 | "---\n", 711 | "\n", 712 | "\n", 713 | "### Exercice 10 : Mesure du temps d'exécution d'une fonction d'analyse\n", 714 | "\n", 715 | "**Objectif :**\n", 716 | "\n", 717 | "Créer un décorateur qui mesure le temps d'exécution d'une fonction.\n", 718 | "\n", 719 | "**Instructions :**\n", 720 | "\n", 721 | "1. Créez un décorateur `mesurer_temps_execution` qui :\n", 722 | "\n", 723 | " - Mesure le temps pris par la fonction pour s'exécuter.\n", 724 | " - Affiche le temps d'exécution avec le nom de la fonction.\n", 725 | "\n", 726 | "2. Appliquez ce décorateur à une fonction `traiter_donnees_historique` qui simule un traitement long (par exemple, en utilisant `time.sleep(2)`).\n", 727 | "\n", 728 | "3. Testez la fonction et vérifiez que le temps d'exécution est affiché.\n", 729 | "\n", 730 | "**Votre code :**" 731 | ] 732 | }, 733 | { 734 | "cell_type": "code", 735 | "execution_count": 29, 736 | "metadata": {}, 737 | "outputs": [], 738 | "source": [ 739 | "# Votre code ici" 740 | ] 741 | }, 742 | { 743 | "cell_type": "markdown", 744 | "metadata": {}, 745 | "source": [ 746 | "
\n", 747 | "Solution Exercice 10 \n", 748 | "\n", 749 | "```python\n", 750 | "import time\n", 751 | "\n", 752 | "def mesurer_temps_execution(fonction):\n", 753 | " def wrapper(*args, **kwargs):\n", 754 | " debut = time.time()\n", 755 | " resultat = fonction(*args, **kwargs)\n", 756 | " fin = time.time()\n", 757 | " print(f\"Temps d'exécution de '{fonction.__name__}': {fin - debut:.4f} secondes\")\n", 758 | " return resultat\n", 759 | " return wrapper\n", 760 | "\n", 761 | "@mesurer_temps_execution\n", 762 | "def traiter_donnees_historique():\n", 763 | " print(\"Traitement des données...\")\n", 764 | " time.sleep(2)\n", 765 | " print(\"Traitement terminé.\")\n", 766 | "\n", 767 | "# Test\n", 768 | "traiter_donnees_historique()\n", 769 | "```" 770 | ] 771 | } 772 | ], 773 | "metadata": { 774 | "kernelspec": { 775 | "display_name": "Python 3", 776 | "language": "python", 777 | "name": "python3" 778 | }, 779 | "language_info": { 780 | "codemirror_mode": { 781 | "name": "ipython", 782 | "version": 3 783 | }, 784 | "file_extension": ".py", 785 | "mimetype": "text/x-python", 786 | "name": "python", 787 | "nbconvert_exporter": "python", 788 | "pygments_lexer": "ipython3", 789 | "version": "3.11.3" 790 | } 791 | }, 792 | "nbformat": 4, 793 | "nbformat_minor": 2 794 | } 795 | -------------------------------------------------------------------------------- /Cours_4_POO_2/Séance 4 - Programmation orientée objet 2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaouabti/Cours_ENC_Introduction_programmation_Python/7dce58e731a47ba702bba33e292090c8b1e7612d/Cours_4_POO_2/Séance 4 - Programmation orientée objet 2.pdf -------------------------------------------------------------------------------- /Cours_5_IIIF_Manipulations_données/Cours_5_Utilisation de l’API IIIF et manipulation de données 1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Cours de Python - IIIF et Manipulation de Fichiers Historiques 1\n", 8 | "\n", 9 | "---\n", 10 | "\n", 11 | "## Table des Matières\n", 12 | "\n", 13 | "1. [Révisions](#Révisions)\n", 14 | " - [Héritage](#Héritage)\n", 15 | " - [Qu'est-ce que l'héritage en POO ?](#Qu'est-ce-que-l'héritage-en-POO-?)\n", 16 | " - [Utilisation de `super()`](#Utilisation-de-super--)\n", 17 | " - [Exemple pratique](#Exemple-pratique)\n", 18 | " - [Les décorateurs](#Les-décorateurs)\n", 19 | " - [Qu'est-ce qu'un décorateur en Python ?](#Qu'est-ce-qu'un-décorateur-en-Python-?)\n", 20 | " - [Pourquoi utiliser des décorateurs ?](#Pourquoi-utiliser-des-décorateurs-?)\n", 21 | " - [Comment fonctionnent les décorateurs ?](#Comment-fonctionnent-les-décorateurs-?)\n", 22 | " - [Les paramètres `*args` et `**kwargs`](#Les-paramètres-args-et-kwargs)\n", 23 | " - [Utilisation de `*args`](#Utilisation-de-args)\n", 24 | " - [Utilisation de `**kwargs`](#Utilisation-de-kwargs)\n", 25 | " - [Combinaison de `*args` et `**kwargs`](#Combinaison-de-args-et-kwargs)\n", 26 | "2. [Introduction à IIIF](#Introduction-à-IIIF)\n", 27 | " - [Qu'est-ce que IIIF ?](#Qu'est-ce-que-IIIF-?)\n", 28 | " - [Les API IIIF](#Les-API-IIIF)\n", 29 | "3. [Structure des Manifestes IIIF](#Structure-des-Manifestes-IIIF)\n", 30 | " - [Le format JSON-LD](#Le-format-JSON-LD)\n", 31 | " - [Composants d'un manifeste IIIF](#Composants-d'un-manifeste-IIIF)\n", 32 | "4. [La bibliothèque `json`](#La-bibliothèque-json)\n", 33 | " - [Chargement de données JSON](#Chargement-de-données-JSON)\n", 34 | " - [Écriture de données JSON](#Écriture-de-données-JSON)\n", 35 | "5. [Parcourir un manifeste IIIF](#Parcourir-un-manifeste-IIIF)\n", 36 | " - [Chargement du manifeste](#Chargement-du-manifeste)\n", 37 | " - [Extraction des métadonnées historiques](#Extraction-des-métadonnées-historiques)\n", 38 | "6. [Manipuler des images avec `PIL`](#Manipuler-des-images-avec-PIL)\n", 39 | " - [Chargement et affichage d'images historiques](#Chargement-et-affichage-d'images-historiques)\n", 40 | " - [Transformation d'images](#Transformation-d'images)\n", 41 | "7. [Gérer le téléchargement avec `os` et `requests`](#Gérer-le-téléchargement-avec-os-et-requests)\n", 42 | " - [Création de répertoires pour les documents historiques](#Création-de-répertoires-pour-les-documents-historiques)\n", 43 | " - [Téléchargement d'images à partir de manifestes IIIF](#Téléchargement-d'images-à-partir-de-manifestes-IIIF)\n", 44 | "8. [Téléchargement multiple d’images](#Téléchargement-multiple-d’images)\n", 45 | " - [Boucle de téléchargement](#Boucle-de-téléchargement)\n", 46 | " - [Améliorations possibles](#Améliorations-possibles)\n", 47 | "\n", 48 | " ----" 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": {}, 54 | "source": [ 55 | "## Révisions\n", 56 | "\n", 57 | "### Héritage\n", 58 | "\n", 59 | "#### Qu'est-ce que l'héritage en POO ?\n", 60 | "\n", 61 | "L'héritage est un mécanisme en programmation orientée objet (POO) qui permet à une classe (appelée **classe enfant** ou **sous-classe**) d'hériter des attributs et méthodes d'une autre classe (appelée **classe parente** ou **super-classe**).\n", 62 | "\n", 63 | "- **But** : Réutiliser du code existant, établir une hiérarchie entre les classes pour une meilleure organisation.\n", 64 | "\n", 65 | "#### Utilisation de `super()`\n", 66 | "\n", 67 | "La fonction `super()` est utilisée pour appeler des méthodes ou des constructeurs de la classe parente.\n", 68 | "\n", 69 | "- **Avantages** :\n", 70 | " - Assure une initialisation correcte des attributs hérités.\n", 71 | " - Permet de réutiliser le code de la classe parente." 72 | ] 73 | }, 74 | { 75 | "cell_type": "markdown", 76 | "metadata": {}, 77 | "source": [ 78 | "#### Exemple pratique\n", 79 | "\n", 80 | "Imaginons que nous travaillons sur des documents historiques et que nous voulons modéliser des types de documents." 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": null, 86 | "metadata": {}, 87 | "outputs": [], 88 | "source": [ 89 | "class DocumentHistorique:\n", 90 | " def __init__(self, titre, date):\n", 91 | " self.titre = titre\n", 92 | " self.date = date\n", 93 | "\n", 94 | " def afficher_info(self):\n", 95 | " print(f\"Titre : {self.titre}\")\n", 96 | " print(f\"Date : {self.date}\")\n", 97 | "\n", 98 | "# Classe enfant\n", 99 | "class Manuscrit(DocumentHistorique):\n", 100 | " def __init__(self, titre, date, auteur):\n", 101 | " super().__init__(titre, date)\n", 102 | " self.auteur = auteur\n", 103 | "\n", 104 | " def afficher_info(self):\n", 105 | " super().afficher_info()\n", 106 | " print(f\"Auteur : {self.auteur}\")" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": null, 112 | "metadata": {}, 113 | "outputs": [], 114 | "source": [ 115 | "manuscrit = Manuscrit(\"Bestiaire divin\", \"XIIIe siècle\", \"Guillaume le Clerc\")\n", 116 | "manuscrit.afficher_info()" 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": {}, 122 | "source": [ 123 | "#### Exercice\n", 124 | "\n", 125 | "Créez une classe `Lettre` qui hérite de `DocumentHistorique` qui ajoute un attribut `destinataire` et modifie la méthode `afficher_info`" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": null, 131 | "metadata": {}, 132 | "outputs": [], 133 | "source": [ 134 | "# Votre code ici" 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": {}, 140 | "source": [ 141 | "---\n", 142 | "\n", 143 | "### Les décorateurs\n", 144 | "\n", 145 | "#### Qu'est-ce qu'un décorateur en Python ?\n", 146 | "\n", 147 | "Un **décorateur** est une fonction qui prend en entrée une autre fonction et retourne une nouvelle fonction avec un comportement modifié ou étendu.\n", 148 | "\n", 149 | "- **But** : Modifier le comportement d'une fonction sans changer son code source.\n", 150 | "\n", 151 | "#### Pourquoi utiliser des décorateurs ?\n", 152 | "\n", 153 | "- **Réutilisation du code** : Appliquer le même comportement à plusieurs fonctions.\n", 154 | "- **Séparation des préoccupations** : Isoler le code additionnel du code principal.\n", 155 | "\n", 156 | "#### Comment fonctionnent les décorateurs ?\n", 157 | "\n", 158 | "Créons un décorateur qui journalise les appels de fonctions, ce qui peut être utile pour suivre les manipulations sur des documents historiques." 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": 1, 164 | "metadata": {}, 165 | "outputs": [ 166 | { 167 | "name": "stdout", 168 | "output_type": "stream", 169 | "text": [ 170 | "Appel de la fonction 'analyser_document' avec les arguments ('The Aberdeen bestiary', '1200') {}\n", 171 | "Analyse du document 'The Aberdeen bestiary' datant de 1200.\n", 172 | "Fin de l'appel de 'analyser_document'\n" 173 | ] 174 | } 175 | ], 176 | "source": [ 177 | "def journaliser(fonction):\n", 178 | " def nouvelle_fonction(*args, **kwargs):\n", 179 | " print(f\"Appel de la fonction '{fonction.__name__}' avec les arguments {args} {kwargs}\")\n", 180 | " resultat = fonction(*args, **kwargs)\n", 181 | " print(f\"Fin de l'appel de '{fonction.__name__}'\")\n", 182 | " return resultat\n", 183 | " return nouvelle_fonction\n", 184 | "\n", 185 | "# Utilisation du décorateur\n", 186 | "@journaliser\n", 187 | "def analyser_document(titre, date):\n", 188 | " print(f\"Analyse du document '{titre}' datant de {date}.\")\n", 189 | "\n", 190 | "# Appel de la fonction\n", 191 | "analyser_document(\"The Aberdeen bestiary\", \"1200\")" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "#### Exercice\n", 199 | "\n", 200 | "Créez un décorateur `verifier_permissions` qui vérifie si un utilisateur a le droit d'accéder à une fonction (par exemple, pour éditer un document historique).\n", 201 | "\n", 202 | "```python\n", 203 | "def verifier_permissions(fonction):\n", 204 | " def wrapper(*args, **kwargs):\n", 205 | " utilisateur_autorise = False # Changez à True pour tester l'accès autorisé\n", 206 | " if utilisateur_autorise:\n", 207 | " return fonction(*args, **kwargs)\n", 208 | " else:\n", 209 | " print(\"Accès refusé : vous n'avez pas les permissions nécessaires.\")\n", 210 | " return wrapper\n", 211 | "\n", 212 | "@verifier_permissions\n", 213 | "def editer_document(titre):\n", 214 | " print(f\"Édition du document '{titre}'.\")\n", 215 | "\n", 216 | "# Testez la fonction\n", 217 | "editer_document(\"Code d'Hammurabi\")" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": null, 223 | "metadata": {}, 224 | "outputs": [], 225 | "source": [ 226 | "# Votre code ici" 227 | ] 228 | }, 229 | { 230 | "cell_type": "markdown", 231 | "metadata": {}, 232 | "source": [ 233 | "---\n", 234 | "\n", 235 | "### Les paramètres `*args` et `**kwargs`\n", 236 | "\n", 237 | "#### Utilisation de `*args`\n", 238 | "\n", 239 | "- **`*args`** permet de passer un nombre variable d'arguments positionnels à une fonction.\n", 240 | "- Les arguments sont accessibles sous forme de **tuple**." 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "execution_count": null, 246 | "metadata": {}, 247 | "outputs": [], 248 | "source": [ 249 | "def lister_evenements(*evenements):\n", 250 | " print(\"Liste des événements historiques :\")\n", 251 | " for evenement in evenements:\n", 252 | " print(f\"- {evenement}\")\n", 253 | "\n", 254 | "# Utilisation\n", 255 | "lister_evenements(\"Fondation de l'Empire akkadien\", \"Civilisation minoenne\", \"Chute de Rome\", \"Règne de saint Louis\")" 256 | ] 257 | }, 258 | { 259 | "cell_type": "markdown", 260 | "metadata": {}, 261 | "source": [ 262 | "#### Utilisation de `**kwargs`\n", 263 | "\n", 264 | "- **`**kwargs`** permet de passer un nombre variable d'arguments nommés à une fonction.\n", 265 | "- Les arguments sont accessibles sous forme de **dictionnaire**." 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": null, 271 | "metadata": {}, 272 | "outputs": [], 273 | "source": [ 274 | "def afficher_informations_document(**infos):\n", 275 | " print(\"Informations sur le document :\")\n", 276 | " for cle, valeur in infos.items():\n", 277 | " print(f\"{cle} : {valeur}\")\n", 278 | "\n", 279 | "# Utilisation\n", 280 | "afficher_informations_document(titre=\"De animalibus\", auteur= 'Albertus Magnus', date=\"1270\", lieu=\"Cologne\")" 281 | ] 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "metadata": {}, 286 | "source": [ 287 | "#### Combinaison de `*args` et `**kwargs`\n", 288 | "\n", 289 | "- Les deux paramètres peuvent être passés simultanment à une fonction. \n", 290 | "- **A noter** : `args` et `kwargs` sont des convebtions de nommage vous pouvez passer le nom des arguments que vous souhaitez en respectant `*` pour les arguments positionnels et `**` pour les arguments nommés." 291 | ] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "execution_count": null, 296 | "metadata": {}, 297 | "outputs": [], 298 | "source": [ 299 | "def fonction_mixte(*args, **kwargs):\n", 300 | " print(\"Arguments positionnels :\", args)\n", 301 | " print(\"Arguments nommés :\", kwargs)\n", 302 | "\n", 303 | "# Utilisation\n", 304 | "fonction_mixte(\"Renaissance\", \"Moyen Âge\", periode1=\"Antiquité\", periode2=\"Époque moderne\")" 305 | ] 306 | }, 307 | { 308 | "cell_type": "markdown", 309 | "metadata": {}, 310 | "source": [ 311 | "---\n", 312 | "\n", 313 | "## Introduction à IIIF\n", 314 | "\n", 315 | "### Qu'est-ce que IIIF ?\n", 316 | "\n", 317 | "- **IIIF** : International Image Interoperability Framework\n", 318 | "- **Objectif** : Fournir un cadre d'interopérabilité pour diffuser, présenter et annoter des images et documents historiques sur le Web.\n", 319 | "\n", 320 | "### Les API IIIF\n", 321 | "\n", 322 | "- **API Présentation** : Décrit la structure, les métadonnées et les liens d'une ressource numérique.\n", 323 | "- **API Image** : Permet d'accéder et de manipuler des images en haute résolution via une syntaxe d'URL standard.\n", 324 | "\n", 325 | "---\n", 326 | "\n", 327 | "## Structure des Manifestes IIIF\n", 328 | "\n", 329 | "### Le format JSON-LD\n", 330 | "\n", 331 | "- **JSON-LD** : Extension de JSON pour intégrer des données liées (Linked Data).\n", 332 | "- Permet d'ajouter du contexte aux données pour une meilleure interopérabilité.\n", 333 | "\n", 334 | "### Composants d'un manifeste IIIF\n", 335 | "\n", 336 | "- **`@context`** : Définit le contexte JSON-LD.\n", 337 | "- **`@id`** : Identifiant unique de la ressource.\n", 338 | "- **`@type`** : Type de la ressource (e.g., `sc:Manifest`).\n", 339 | "- **`label`** : Titre ou nom de la ressource.\n", 340 | "- **`metadata`** : Liste de métadonnées supplémentaires.\n", 341 | "- **`items`** ou **`sequences`** : Liste des éléments structurants (pages, images).\n", 342 | "\n", 343 | "---" 344 | ] 345 | }, 346 | { 347 | "cell_type": "markdown", 348 | "metadata": {}, 349 | "source": [ 350 | "## La bibliothèque `json`\n", 351 | "\n", 352 | "### Chargement de données JSON\n", 353 | "\n", 354 | "La bibliothèque `json` est essentielle pour manipuler des données au format JSON, comme les manifestes IIIF." 355 | ] 356 | }, 357 | { 358 | "cell_type": "code", 359 | "execution_count": null, 360 | "metadata": {}, 361 | "outputs": [], 362 | "source": [ 363 | "import json\n", 364 | "\n", 365 | "# Charger un fichier JSON local\n", 366 | "with open('document_historique.json', 'r', encoding='utf-8') as fichier:\n", 367 | " data = json.load(fichier)\n", 368 | "\n", 369 | "# Charger des données JSON depuis une chaîne\n", 370 | "json_str = '{\"titre\": \"Déclaration d\\'indépendance des États-Unis\", \"date\": \"1776\"}'\n", 371 | "data = json.loads(json_str)\n", 372 | "print(data)" 373 | ] 374 | }, 375 | { 376 | "cell_type": "markdown", 377 | "metadata": {}, 378 | "source": [ 379 | "### Écriture de données JSON" 380 | ] 381 | }, 382 | { 383 | "cell_type": "code", 384 | "execution_count": null, 385 | "metadata": {}, 386 | "outputs": [], 387 | "source": [ 388 | "import json\n", 389 | "\n", 390 | "# Écrire des données dans un fichier JSON\n", 391 | "document = {\n", 392 | " 'titre': 'Constitution française',\n", 393 | " 'date': '1791',\n", 394 | " 'auteurs': ['Assemblée nationale']\n", 395 | "}\n", 396 | "with open('constitution_1791.json', 'w', encoding='utf-8') as fichier:\n", 397 | " json.dump(document, fichier, indent=4, ensure_ascii=False)" 398 | ] 399 | }, 400 | { 401 | "cell_type": "markdown", 402 | "metadata": {}, 403 | "source": [ 404 | "- **Note** : L'option `ensure_ascii=False` permet de conserver les caractères spéciaux (accents) lors de l'écriture.\n", 405 | "\n", 406 | "---" 407 | ] 408 | }, 409 | { 410 | "cell_type": "markdown", 411 | "metadata": {}, 412 | "source": [ 413 | "## Parcourir un manifeste IIIF\n", 414 | "\n", 415 | "### Chargement du manifeste\n", 416 | "\n", 417 | "Nous allons travailler avec le manifeste de **Gallica** :" 418 | ] 419 | }, 420 | { 421 | "cell_type": "code", 422 | "execution_count": null, 423 | "metadata": {}, 424 | "outputs": [], 425 | "source": [ 426 | "import json\n", 427 | "\n", 428 | "def open_json(json_file):\n", 429 | " with open(json_file, 'r') as readable_json:\n", 430 | " manifeste = json.load(readable_json)\n", 431 | " return manifeste" 432 | ] 433 | }, 434 | { 435 | "cell_type": "code", 436 | "execution_count": null, 437 | "metadata": {}, 438 | "outputs": [], 439 | "source": [] 440 | }, 441 | { 442 | "cell_type": "markdown", 443 | "metadata": {}, 444 | "source": [ 445 | "### Extraction des métadonnées historiques\n", 446 | "\n", 447 | "Deux manières de parcourir un manifeste : \n", 448 | "- Comme un dictionaire en appelant les clés et les valeurs (Exemple 1)\n", 449 | "- En parcourant simplement les clés (Exemple 1) : plus fluide pour récupérer les données qui nous intéresse et parourir la structure" 450 | ] 451 | }, 452 | { 453 | "cell_type": "code", 454 | "execution_count": null, 455 | "metadata": {}, 456 | "outputs": [], 457 | "source": [ 458 | "iiif_manifest = open_json('pathtomanifeste')\n", 459 | "\n", 460 | "# Exemple 1\n", 461 | "for key, value in iiif_manifest.items():\n", 462 | " print(key)\n", 463 | "\n", 464 | "# Exemple 2\n", 465 | "for item in iiif_manifest:\n", 466 | " print(item)\n", 467 | "\n", 468 | "# Avantage de la deuxième pour taper sur les clés qui nous intéresse\n", 469 | "# id = iiif_manifest['@id']" 470 | ] 471 | }, 472 | { 473 | "cell_type": "markdown", 474 | "metadata": {}, 475 | "source": [ 476 | "#### Exercice\n", 477 | "\n", 478 | "- Chargez l'un des manifestes suivants :\n", 479 | "\n", 480 | " - **BVMM** : `https://bvmm.irht.cnrs.fr/iiif/22470/manifest`\n", 481 | " - **e-codices** : `https://www.e-codices.unifr.ch/metadata/iiif/bbb-0318/manifest.json`\n", 482 | "\n", 483 | "- Affichez le titre et les métadonnées du manifeste." 484 | ] 485 | }, 486 | { 487 | "cell_type": "code", 488 | "execution_count": null, 489 | "metadata": {}, 490 | "outputs": [], 491 | "source": [ 492 | "# Votre code ici" 493 | ] 494 | }, 495 | { 496 | "cell_type": "markdown", 497 | "metadata": {}, 498 | "source": [ 499 | "---\n", 500 | "\n", 501 | "## Manipuler des images avec `PIL`\n", 502 | "\n", 503 | "### Chargement et affichage d'images historiques\n", 504 | "\n", 505 | "Nous allons manipuler des images issus de l'un des manifestes précédents" 506 | ] 507 | }, 508 | { 509 | "cell_type": "code", 510 | "execution_count": null, 511 | "metadata": {}, 512 | "outputs": [], 513 | "source": [ 514 | "from PIL import Image\n", 515 | "\n", 516 | "# Ouvrir une image locale\n", 517 | "image = Image.open('pathto/img.jpg')\n", 518 | "\n", 519 | "# Afficher l'image\n", 520 | "image.show()" 521 | ] 522 | }, 523 | { 524 | "cell_type": "markdown", 525 | "metadata": {}, 526 | "source": [ 527 | "### Transformation d'images\n", 528 | "\n", 529 | "Par exemple, nous pouvons améliorer la lisibilité d'un manuscrit ancien." 530 | ] 531 | }, 532 | { 533 | "cell_type": "code", 534 | "execution_count": null, 535 | "metadata": {}, 536 | "outputs": [], 537 | "source": [ 538 | "# Convertir en niveaux de gris\n", 539 | "image_gris = image.convert('L')\n", 540 | "\n", 541 | "# Augmenter le contraste\n", 542 | "from PIL import ImageEnhance\n", 543 | "\n", 544 | "enhancer = ImageEnhance.Contrast(image_gris)\n", 545 | "image_contraste = enhancer.enhance(2) # Augmenter le contraste par un facteur de 2\n", 546 | "\n", 547 | "# Enregistrer l'image modifiée\n", 548 | "image_contraste.save('images_historique/page1_contraste.jpg')\n", 549 | "\n", 550 | "# Afficher l'image modifiée\n", 551 | "image_contraste.show()" 552 | ] 553 | }, 554 | { 555 | "cell_type": "markdown", 556 | "metadata": {}, 557 | "source": [ 558 | "#### Exercice interactif\n", 559 | "\n", 560 | "- Chargez une image de votre choix.\n", 561 | "- Effectuez les opérations suivantes :\n", 562 | " - Redimensionnez l'image pour qu'elle ait une largeur de 800 pixels tout en conservant le ratio.\n", 563 | " - Appliquez un filtre de netteté pour améliorer la lisibilité (parcourir la doc : https://pillow.readthedocs.io/en/stable/reference/ImageFilter.html)." 564 | ] 565 | }, 566 | { 567 | "cell_type": "code", 568 | "execution_count": null, 569 | "metadata": {}, 570 | "outputs": [], 571 | "source": [ 572 | "# Votre code ici" 573 | ] 574 | }, 575 | { 576 | "cell_type": "markdown", 577 | "metadata": {}, 578 | "source": [ 579 | "---\n", 580 | "\n", 581 | "## Gérer le téléchargement avec `os` et `requests`\n", 582 | "\n", 583 | "### Création de répertoires pour les documents historiques" 584 | ] 585 | }, 586 | { 587 | "cell_type": "code", 588 | "execution_count": 2, 589 | "metadata": {}, 590 | "outputs": [ 591 | { 592 | "name": "stdout", 593 | "output_type": "stream", 594 | "text": [ 595 | "Dossier 'pathtofolder' créé.\n" 596 | ] 597 | } 598 | ], 599 | "source": [ 600 | "import os\n", 601 | "\n", 602 | "# Chemin du répertoire\n", 603 | "dossier_images = 'pathtofolder'\n", 604 | "\n", 605 | "# Créer le répertoire s'il n'existe pas\n", 606 | "if not os.path.exists(dossier_images):\n", 607 | " os.makedirs(dossier_images)\n", 608 | " print(f\"Dossier '{dossier_images}' créé.\")\n", 609 | "else:\n", 610 | " print(f\"Dossier '{dossier_images}' existe déjà.\")" 611 | ] 612 | }, 613 | { 614 | "cell_type": "markdown", 615 | "metadata": {}, 616 | "source": [ 617 | "### Téléchargement d'images à partir de manifestes IIIF\n", 618 | "\n", 619 | "Nous allons télécharger une image à partir du manifeste chargé précédemment, en suivant les étapes :\n", 620 | "- Ouvrir le manifeste en ligne\n", 621 | "- Parcourir la structure pour trouver l'url de la première image\n", 622 | "- L'enregistrer dans un dossier spécifique avec comme nom `image_(numéro canvas + 1)`" 623 | ] 624 | }, 625 | { 626 | "cell_type": "code", 627 | "execution_count": null, 628 | "metadata": {}, 629 | "outputs": [], 630 | "source": [ 631 | "import requests\n", 632 | "import os\n", 633 | "import time\n", 634 | "\n", 635 | "def download_image_from_url(image_url: str, dir_path: str, request_pause: int) -> None:\n", 636 | " \"\"\"\n", 637 | " Télécharge une image à partir d'une URL et l'enregistre sous forme de fichier.\n", 638 | "\n", 639 | " Paramètres :\n", 640 | " - image_url (str) : URL de l'image à télécharger.\n", 641 | " - dir_path (str) : Chemin du dossier où l'image sera enregistrée, y compris le nom du fichier.\n", 642 | " - request_pause (int) : Durée de la pause en secondes après la requête.\n", 643 | " \"\"\"\n", 644 | " \n", 645 | " print(f'Téléchargement de l\\'image depuis {image_url}')\n", 646 | "\n", 647 | " try:\n", 648 | " # Requête pour télécharger l'image\n", 649 | " r = requests.get(image_url, stream=True)\n", 650 | " print(f\"Code de statut : {r.status_code}\")\n", 651 | "\n", 652 | " # Vérifie si l'image a été récupérée avec succès\n", 653 | " if r.status_code == 200:\n", 654 | " # Marquer le contenu pour décodage (nécessaire pour certains types de réponses brutes)\n", 655 | " r.raw.decode_content = True\n", 656 | "\n", 657 | " # Ouvrir le fichier de destination en mode écriture binaire\n", 658 | " with open(dir_path, 'wb') as image_file:\n", 659 | " image_file.write(r.content) # Écriture directe du contenu\n", 660 | "\n", 661 | " # Pause après la requête\n", 662 | " time.sleep(request_pause)\n", 663 | " print(\"Image téléchargée et sauvegardée avec succès.\")\n", 664 | " else:\n", 665 | " print(f\"Échec du téléchargement de l'image depuis {image_url}. Code de statut : {r.status_code}\")\n", 666 | "\n", 667 | " except requests.exceptions.SSLError as e:\n", 668 | " print(f\"Erreur SSL lors du téléchargement de l'image depuis {image_url}. Message d'erreur : {str(e)}\")\n", 669 | " except Exception as e:\n", 670 | " print(f\"Erreur lors du téléchargement de l'image depuis {image_url}. Message d'erreur : {str(e)}\")\n", 671 | "\n", 672 | "# Exemple d'utilisation\n", 673 | "image_url = 'https://www.e-codices.unifr.ch/loris/bbb/bbb-0318/bbb-0318_008r.jp2/full/full/0/default.jpg'\n", 674 | "dir_path = os.path.join('/Users/marioncharpier/Documents/Cours_ENC/IIIF_Images', 'img1.jpg')\n", 675 | "request_pause = 0\n", 676 | "download_image_from_url(image_url, dir_path, request_pause)" 677 | ] 678 | } 679 | ], 680 | "metadata": { 681 | "kernelspec": { 682 | "display_name": "iiif_env", 683 | "language": "python", 684 | "name": "iiif_env" 685 | }, 686 | "language_info": { 687 | "codemirror_mode": { 688 | "name": "ipython", 689 | "version": 3 690 | }, 691 | "file_extension": ".py", 692 | "mimetype": "text/x-python", 693 | "name": "python", 694 | "nbconvert_exporter": "python", 695 | "pygments_lexer": "ipython3", 696 | "version": "3.8.0" 697 | } 698 | }, 699 | "nbformat": 4, 700 | "nbformat_minor": 2 701 | } 702 | -------------------------------------------------------------------------------- /Cours_5_IIIF_Manipulations_données/Séance 5 - Introduction à IIIF et à la manipulation de fichiers.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaouabti/Cours_ENC_Introduction_programmation_Python/7dce58e731a47ba702bba33e292090c8b1e7612d/Cours_5_IIIF_Manipulations_données/Séance 5 - Introduction à IIIF et à la manipulation de fichiers.pdf -------------------------------------------------------------------------------- /Cours_6_Utilisation_IIIF_manipulation_données_2/Cours_6_IIIF_manipulations_2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Cours de Python - Utilisation de l'API IIIF et manipulation de données 2" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "---\n", 15 | "\n", 16 | "## Table des Matières\n", 17 | "\n", 18 | "1. [Révisions](#révisions)\n", 19 | " - [Structure des manifestes](#structure-des-manifestes)\n", 20 | " - [Les principales composantes](#les-principales-composantes)\n", 21 | " - [Les canvas](#les-canvas)\n", 22 | " - [Trouver l'URL de l'image](#trouver-lurl-de-limage)\n", 23 | " - [Bibliothèque JSON](#bibliothèque-json)\n", 24 | " - [Rappel sur la bibliothèque](#rappel-sur-la-bibliothèque)\n", 25 | " - [Ouvrir un fichier JSON](#ouvrir-un-fichier-json)\n", 26 | " - [Écrire et enregistrer un fichier JSON](#écrire-et-enregistrer-un-fichier-json)\n", 27 | " - [La bibliothèque `os`](#la-bibliothèque-os)\n", 28 | " - [Intérêt de `os`](#intérêt-de-os)\n", 29 | " - [Création de filepath](#création-de-filepath)\n", 30 | " - [Création de dossier](#création-de-dossier)\n", 31 | "2. [Télécharger des données avec la bibliothèque `requests`](#télécharger-des-données-avec-la-bibliothèque-requests)\n", 32 | " - [Intérêt de la bibliothèque](#intérêt-de-la-bibliothèque)\n", 33 | " - [Manipulation des codes et gestion des exceptions](#manipulation-des-codes-et-gestion-des-exceptions)\n", 34 | " - [Méthode `get` et gérer les `status_code`](#méthode-get-et-gérer-les-status_code)\n", 35 | " - [Téléchargement avec `requests'](#téléchargement-avec-requests)\n", 36 | "3. [Manipuler des images](#manipuler-des-images)\n", 37 | " - [La bibliothèque PIL](#la-bibliothèque-pil)\n", 38 | " - [Manipulation de base d'une image](#manipulation-de-base-dune-image)\n", 39 | " - [Récupérer les données des images](#récupérer-les-données-des-images)\n", 40 | "\n", 41 | "---" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "## Révisions\n", 49 | "\n", 50 | "### Structure des manifestes\n", 51 | "\n", 52 | "#### Les principales composantes\n", 53 | "\n", 54 | "Un **manifeste** est un document structuré qui décrit une ressource numérique complexe. Il est souvent utilisé pour représenter des collections d'images, de textes ou de médias. Dans le contexte de l'histoire numérique, les manifestes facilitent l'accès et l'interopérabilité des ressources historiques en ligne.\n", 55 | "\n", 56 | "- **Identifiant unique (`@id`)** : Un URL unique qui identifie le manifeste.\n", 57 | "- **Type (`@type`)** : Indique le type de ressource (par exemple, \"sc:Manifest\").\n", 58 | "- **Métadonnées (`metadata`)** : Informations sur la ressource, telles que le titre, le créateur, la date, etc.\n", 59 | "- **Séquences (`sequences`)** : Liste des séquences de contenu, généralement une seule séquence nommée \"normal\".\n", 60 | "- **Canvases (`canvases`)** : Représente les unités de contenu individuelles, comme les pages d'un livre, les folios d'un manuscrit ou les images d'une collection.\n", 61 | "\n", 62 | "Exemple d'un manifeste simplifié au format JSON :\n" 63 | ] 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "metadata": {}, 68 | "source": [ 69 | "```json\n", 70 | "{\n", 71 | " \"@context\": \"http://iiif.io/api/presentation/2/context.json\",\n", 72 | " \"@id\": \"http://example.org/manifest.json\",\n", 73 | " \"@type\": \"sc:Manifest\",\n", 74 | " \"label\": \"Titre de la ressource\",\n", 75 | " \"metadata\": [\n", 76 | " {\n", 77 | " \"label\": \"Créateur\",\n", 78 | " \"value\": \"Nom du créateur\"\n", 79 | " }\n", 80 | " ],\n", 81 | " \"sequences\": [\n", 82 | " {\n", 83 | " \"@type\": \"sc:Sequence\",\n", 84 | " \"canvases\": [\n", 85 | " {\n", 86 | " \"@id\": \"http://example.org/canvas/p1\",\n", 87 | " \"@type\": \"sc:Canvas\",\n", 88 | " \"label\": \"Page 1\",\n", 89 | " \"images\": [\n", 90 | " {\n", 91 | " \"@type\": \"oa:Annotation\",\n", 92 | " \"motivation\": \"sc:painting\",\n", 93 | " \"resource\": {\n", 94 | " \"@id\": \"http://example.org/image/p1/full/full/0/default.jpg\",\n", 95 | " \"@type\": \"dctypes:Image\",\n", 96 | " \"format\": \"image/jpeg\",\n", 97 | " \"width\": 1000,\n", 98 | " \"height\": 1500\n", 99 | " },\n", 100 | " \"on\": \"http://example.org/canvas/p1\"\n", 101 | " }\n", 102 | " ]\n", 103 | " }\n", 104 | " ]\n", 105 | " }\n", 106 | " ]\n", 107 | "}\n", 108 | "```" 109 | ] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "metadata": {}, 114 | "source": [ 115 | "#### Les canvas\n", 116 | "\n", 117 | "Un **canvas** représente une unité de contenu, comme une page ou une image individuelle. Il est essentiel pour structurer et naviguer à travers une collection ou un document complexe.\n", 118 | "\n", 119 | "Propriétés d'un canvas :\n", 120 | "\n", 121 | "- **Identifiant (`@id`)** : URL unique du canvas.\n", 122 | "- **Type (`@type`)** : Généralement \"sc:Canvas\".\n", 123 | "- **Label** : Nom ou titre du canvas.\n", 124 | "- **Dimensions** : Largeur et hauteur du canvas.\n", 125 | "- **Images** : Liste des annotations d'images associées au canvas. L'annotation dans le contexte de IIIF contient des informations sur l'image, telles que :\n", 126 | " - @type : Type de l'annotation, par exemple, \"Annotation\".\n", 127 | " - motivation : But de l'annotation. Pour une image, c'est souvent \"sc:painting\", ce qui signifie qu'elle est peinte ou placée sur le canvas.\n", 128 | " - resource : La ressource multimédia, souvent un lien vers l'image elle-même. Il peut contenir des détails sur la taille de l'image et des informations de type MIME (comme image/jpeg).\n", 129 | " - on : Référence au canvas sur lequel l'image doit être affichée. Cela associe l'image à un endroit spécifique sur ce canvas." 130 | ] 131 | }, 132 | { 133 | "cell_type": "markdown", 134 | "metadata": {}, 135 | "source": [ 136 | "```json\n", 137 | "{\n", 138 | " \"@id\": \"https://www.e-codices.unifr.ch/metadata/iiif/bbb-0318/canvas/bbb-0318_001r.json\",\n", 139 | " \"@type\": \"sc:Canvas\",\n", 140 | " \"label\": \"1r\",\n", 141 | " \"height\": 6496,\n", 142 | " \"width\": 4872,\n", 143 | " \"images\": [\n", 144 | " {\n", 145 | " \"@id\": \"https://www.e-codices.unifr.ch/metadata/iiif/bbb-0318/annotation/bbb-0318_001r.json\",\n", 146 | " \"@type\": \"oa:Annotation\",\n", 147 | " \"motivation\": \"sc:painting\",\n", 148 | " \"on\": \"https://www.e-codices.unifr.ch/metadata/iiif/bbb-0318/canvas/bbb-0318_001r.json\",\n", 149 | " \"resource\": {\n", 150 | " \"@id\": \"https://www.e-codices.unifr.ch/loris/bbb/bbb-0318/bbb-0318_001r.jp2/full/full/0/default/jpg\",\n", 151 | " \"@type\": \"dctypes:Image\",\n", 152 | " \"format\": \"image/jpeg\",\n", 153 | " \"height\": 6496,\n", 154 | " \"width\": 4872,\n", 155 | " \"service\": {\n", 156 | " \"@context\": \"http://iiif.io/api/image/2/context.json\",\n", 157 | " \"@id\": \"https://www.e-codices.unifr.ch/loris/bbb/bbb-0318/bbb-0318_001r.jp2\",\n", 158 | " \"profile\": \"http://iiif.io/api/image/2/level2.json\"\n", 159 | " }\n", 160 | " }\n", 161 | " }\n", 162 | " ]\n", 163 | "}" 164 | ] 165 | }, 166 | { 167 | "cell_type": "markdown", 168 | "metadata": {}, 169 | "source": [ 170 | "#### Trouver l'URL de l'image\n", 171 | "\n", 172 | "Pour extraire l'URL d'une image spécifique à partir d'un manifeste, vous devez naviguer à travers la structure imbriquée du JSON." 173 | ] 174 | }, 175 | { 176 | "cell_type": "markdown", 177 | "metadata": {}, 178 | "source": [ 179 | "Exemple en Python :\n", 180 | "\n", 181 | "```python\n", 182 | "import json\n", 183 | "\n", 184 | "# Charger le manifeste\n", 185 | "with open('manifest.json', 'r') as file:\n", 186 | " manifest = json.load(file)\n", 187 | "\n", 188 | "# Accéder au premier canvas\n", 189 | "canvas = manifest['sequences'][0]['canvases'][0]\n", 190 | "\n", 191 | "# Accéder à l'annotation de l'image\n", 192 | "annotation = canvas['images'][0]\n", 193 | "\n", 194 | "# URL de l'image\n", 195 | "image_url = annotation['resource']['@id']\n", 196 | "\n", 197 | "print(\"URL de l'image :\", image_url)\n", 198 | "```" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": 33, 204 | "metadata": {}, 205 | "outputs": [], 206 | "source": [ 207 | "import json\n", 208 | "\n", 209 | "def find_url_img(iiif_manifest):\n", 210 | " with open(iiif_manifest, 'r') as file:\n", 211 | " manifest = json.load(file)\n", 212 | "\n", 213 | " # Accéder au premier canvas\n", 214 | " canvas = manifest['sequences'][0]['canvases'][0]\n", 215 | "\n", 216 | " # Accéder à l'annotation de l'image\n", 217 | " annotation = canvas['images'][0]\n", 218 | "\n", 219 | " # URL de l'image\n", 220 | " image_url = annotation['resource']['@id']\n", 221 | "\n", 222 | " print(\"URL de l'image :\", image_url)" 223 | ] 224 | }, 225 | { 226 | "cell_type": "markdown", 227 | "metadata": {}, 228 | "source": [ 229 | "---\n", 230 | "\n", 231 | "### Bibliothèque JSON\n", 232 | "\n", 233 | "#### Rappel sur la bibliothèque\n", 234 | "\n", 235 | "La bibliothèque `json` est intégrée à Python et permet de travailler facilement avec des données au format JSON.\n", 236 | "\n", 237 | "- **JSON** (JavaScript Object Notation) est un format léger d'échange de données, facile à lire et à écrire pour les humains, et facile à analyser et générer pour les machines.\n", 238 | "\n", 239 | "#### Ouvrir un fichier JSON\n", 240 | "\n", 241 | "Pour lire un fichier JSON en Python :\n", 242 | "\n", 243 | "```python\n", 244 | "import json\n", 245 | "\n", 246 | "with open('data.json', 'r', encoding='utf-8') as file:\n", 247 | " data = json.load(file)\n", 248 | "\n", 249 | "print(data)\n", 250 | "```\n", 251 | "\n", 252 | "Gestion des exceptions :\n", 253 | "\n", 254 | "```python\n", 255 | "try:\n", 256 | " with open('data.json', 'r', encoding='utf-8') as file:\n", 257 | " data = json.load(file)\n", 258 | "except json.JSONDecodeError as e:\n", 259 | " print(\"Erreur lors du décodage JSON :\", e)\n", 260 | "except FileNotFoundError:\n", 261 | " print(\"Fichier non trouvé.\")\n", 262 | "```" 263 | ] 264 | }, 265 | { 266 | "cell_type": "markdown", 267 | "metadata": {}, 268 | "source": [ 269 | "#### Écrire et enregistrer un fichier JSON\n", 270 | "\n", 271 | "Pour écrire des données Python dans un fichier JSON :\n", 272 | "\n", 273 | "```python\n", 274 | "import json\n", 275 | "\n", 276 | "data = {\n", 277 | " 'name': 'Historien',\n", 278 | " 'projets': ['numérisation', 'analyse']\n", 279 | "}\n", 280 | "\n", 281 | "with open('output.json', 'w', encoding='utf-8') as file:\n", 282 | " json.dump(data, file, indent=4, ensure_ascii=False)\n", 283 | "```\n", 284 | "\n", 285 | "Notes :\n", 286 | "\n", 287 | "- `indent=4` : pour une indentation de 4 espaces, améliore la lisibilité.\n", 288 | "- `ensure_ascii=False` : pour conserver les caractères spéciaux (accents, etc.).\n", 289 | "\n", 290 | "---" 291 | ] 292 | }, 293 | { 294 | "cell_type": "markdown", 295 | "metadata": {}, 296 | "source": [ 297 | "### La bibliothèque `os`\n", 298 | "\n", 299 | "#### Intérêt de `os`\n", 300 | "\n", 301 | "La bibliothèque `os` permet d'interagir avec le système d'exploitation :\n", 302 | "\n", 303 | "- Gestion des fichiers et répertoires.\n", 304 | "- Exécution de commandes système.\n", 305 | "- Accès aux variables d'environnement." 306 | ] 307 | }, 308 | { 309 | "cell_type": "markdown", 310 | "metadata": {}, 311 | "source": [ 312 | "#### Création de filepath\n", 313 | "\n", 314 | "Construction de chemins de fichiers de manière indépendante du système :\n", 315 | "\n", 316 | "```python\n", 317 | "import os\n", 318 | "\n", 319 | "# Chemin relatif\n", 320 | "chemin = os.path.join('dossier', 'sous_dossier', 'fichier.txt')\n", 321 | "print(chemin)\n", 322 | "\n", 323 | "# Chemin absolu\n", 324 | "chemin_absolu = os.path.abspath(chemin)\n", 325 | "print(chemin_absolu)\n", 326 | "```" 327 | ] 328 | }, 329 | { 330 | "cell_type": "markdown", 331 | "metadata": {}, 332 | "source": [ 333 | "Fonctions utiles :\n", 334 | "\n", 335 | "- `os.path.exists(chemin)` : Vérifie si le chemin existe.\n", 336 | "- `os.path.dirname(chemin)` : Renvoie le répertoire parent.\n", 337 | "- `os.path.basename(chemin)` : Renvoie le nom du fichier." 338 | ] 339 | }, 340 | { 341 | "cell_type": "markdown", 342 | "metadata": {}, 343 | "source": [ 344 | "#### Création de dossier\n", 345 | "\n", 346 | "Créer un seul dossier :\n", 347 | "\n", 348 | "```python\n", 349 | "import os\n", 350 | "\n", 351 | "dossier = 'nouveau_dossier'\n", 352 | "\n", 353 | "if not os.path.exists(dossier):\n", 354 | " os.mkdir(dossier)\n", 355 | " print(f\"Dossier '{dossier}' créé.\")\n", 356 | "else:\n", 357 | " print(f\"Dossier '{dossier}' existe déjà.\")\n", 358 | "```" 359 | ] 360 | }, 361 | { 362 | "cell_type": "markdown", 363 | "metadata": {}, 364 | "source": [ 365 | "Créer des répertoires imbriqués :\n", 366 | "\n", 367 | "```python\n", 368 | "dossiers = os.path.join('dossier1', 'dossier2', 'dossier3')\n", 369 | "\n", 370 | "if not os.path.exists(dossiers):\n", 371 | " os.makedirs(dossiers)\n", 372 | " print(f\"Dossiers '{dossiers}' créés.\")\n", 373 | "else:\n", 374 | " print(f\"Dossiers '{dossiers}' existent déjà.\")\n", 375 | "```" 376 | ] 377 | }, 378 | { 379 | "cell_type": "markdown", 380 | "metadata": {}, 381 | "source": [ 382 | "Gestion des exceptions :\n", 383 | "\n", 384 | "```python\n", 385 | "try:\n", 386 | " os.makedirs(dossiers, exist_ok=True)\n", 387 | "except OSError as e:\n", 388 | " if e.errno == os.errno.EEXIST:\n", 389 | " print(\"Le dossier existe déjà.\")\n", 390 | " else:\n", 391 | " raise\n", 392 | "```\n", 393 | "\n", 394 | "Plus simplement \n", 395 | "\n", 396 | "```python\n", 397 | "os.makedirs(dossiers, exist_ok=True)\n", 398 | "```\n", 399 | "\n" 400 | ] 401 | }, 402 | { 403 | "cell_type": "markdown", 404 | "metadata": {}, 405 | "source": [ 406 | "---\n", 407 | "\n", 408 | "## Télécharger des données avec la bibliothèque `requests`\n", 409 | "\n", 410 | "### Intérêt de la bibliothèque\n", 411 | "\n", 412 | "La bibliothèque `requests` simplifie les requêtes HTTP en Python :\n", 413 | "\n", 414 | "- Plus conviviale que le module intégré `urllib`.\n", 415 | "- Gère les sessions, les cookies, l'authentification, etc.\n", 416 | "- Bien documentée et largement utilisée.\n", 417 | "\n", 418 | "Installation :\n", 419 | "\n", 420 | "```bash\n", 421 | "pip install requests\n", 422 | "```" 423 | ] 424 | }, 425 | { 426 | "cell_type": "markdown", 427 | "metadata": {}, 428 | "source": [ 429 | "### Manipulation des codes et gestion des exceptions\n", 430 | "\n", 431 | "Comprendre les codes de statut HTTP :\n", 432 | "\n", 433 | "- **200** : OK (succès).\n", 434 | "- **404** : Not Found (non trouvé).\n", 435 | "- **429** : Too Many Requests\n", 436 | "- **500** : Internal Server Error (erreur serveur).\n", 437 | "\n", 438 | "Exemple :" 439 | ] 440 | }, 441 | { 442 | "cell_type": "code", 443 | "execution_count": null, 444 | "metadata": {}, 445 | "outputs": [ 446 | { 447 | "name": "stdout", 448 | "output_type": "stream", 449 | "text": [ 450 | "Code de statut : 200\n" 451 | ] 452 | } 453 | ], 454 | "source": [ 455 | "import requests\n", 456 | "\n", 457 | "response = requests.get('https://www.e-codices.unifr.ch/metadata/iiif/bbb-0318/manifest.json')\n", 458 | "\n", 459 | "print(\"Code de statut :\", response.status_code)" 460 | ] 461 | }, 462 | { 463 | "cell_type": "markdown", 464 | "metadata": {}, 465 | "source": [ 466 | "### 2.3 Méthode `get` et gérer les `status_code`\n", 467 | "\n", 468 | "Gestion des erreurs :\n", 469 | "\n", 470 | "```python\n", 471 | "if response.status_code == 200:\n", 472 | " data = response.json()\n", 473 | "else:\n", 474 | " print(f\"Erreur {response.status_code} lors de la requête.\")\n", 475 | "```" 476 | ] 477 | }, 478 | { 479 | "cell_type": "markdown", 480 | "metadata": {}, 481 | "source": [ 482 | "Exceptions de `requests` :\n", 483 | "\n", 484 | "```python\n", 485 | "import requests\n", 486 | "\n", 487 | "try:\n", 488 | " response = requests.get('https://api.example.com/data')\n", 489 | " response.raise_for_status() # Lève une exception pour les codes d'erreur HTTP\n", 490 | " data = response.json()\n", 491 | "except requests.exceptions.HTTPError as errh:\n", 492 | " print(\"Erreur HTTP :\", errh)\n", 493 | "except requests.exceptions.ConnectionError as errc:\n", 494 | " print(\"Erreur de connexion :\", errc)\n", 495 | "except requests.exceptions.Timeout as errt:\n", 496 | " print(\"Délai d'attente dépassé :\", errt)\n", 497 | "except requests.exceptions.RequestException as err:\n", 498 | " print(\"Erreur lors de la requête :\", err)\n", 499 | "```" 500 | ] 501 | }, 502 | { 503 | "cell_type": "markdown", 504 | "metadata": {}, 505 | "source": [ 506 | "### Téléchargement avec `requests'\n", 507 | "\n", 508 | "#### Télécharger un manifeste depuis une URL :" 509 | ] 510 | }, 511 | { 512 | "cell_type": "code", 513 | "execution_count": null, 514 | "metadata": {}, 515 | "outputs": [], 516 | "source": [ 517 | "import json\n", 518 | "import requests\n", 519 | "import os\n", 520 | "\n", 521 | "def download_manifest(manifest_url, output_folder, ms_name):\n", 522 | " # URL du manifeste IIIF\n", 523 | " manifest_url = 'https://www.e-codices.unifr.ch/metadata/iiif/bbb-0318/manifest.json'\n", 524 | "\n", 525 | " # Télécharger le manifeste\n", 526 | " response = requests.get(manifest_url)\n", 527 | "\n", 528 | " # Vérifier que la requête s'est bien passée\n", 529 | " if response.status_code == 200:\n", 530 | " manifest = response.json()\n", 531 | " print(\"Manifeste chargé avec succès.\")\n", 532 | " manifest_path = os.path.join(output_folder, ms_name + '_manifest.json')\n", 533 | " \n", 534 | " # Save the manifest.json file in the destination folder\n", 535 | " with open(manifest_path, 'wb') as f:\n", 536 | " f.write(response.content)\n", 537 | " print(f\"Manifeste téléchargé dans : {os.path.join(output_folder, ms_name + '_manifest.json')}\")\n", 538 | " else:\n", 539 | " print(f\"Erreur lors du chargement du manifeste : {response.status_code}\")" 540 | ] 541 | }, 542 | { 543 | "cell_type": "markdown", 544 | "metadata": {}, 545 | "source": [ 546 | "#### Téléchargement d'image\n", 547 | "\n", 548 | "Télécharger une image depuis une URL :" 549 | ] 550 | }, 551 | { 552 | "cell_type": "code", 553 | "execution_count": null, 554 | "metadata": {}, 555 | "outputs": [ 556 | { 557 | "name": "stdout", 558 | "output_type": "stream", 559 | "text": [ 560 | "Image téléchargée avec succès.\n" 561 | ] 562 | } 563 | ], 564 | "source": [ 565 | "import requests\n", 566 | "\n", 567 | "url = 'https://www.e-codices.unifr.ch/loris/bbb/bbb-0318/bbb-0318_001r.jp2/full/full/0/default/jpg'\n", 568 | "\n", 569 | "try:\n", 570 | " response = requests.get(url)\n", 571 | " response.raise_for_status()\n", 572 | " \n", 573 | " # Vérifier le type de contenu\n", 574 | " if url.endswith('jpg'):\n", 575 | " with open('image.jpg', 'wb') as file:\n", 576 | " file.write(response.content)\n", 577 | " print(\"Image téléchargée avec succès.\")\n", 578 | " else:\n", 579 | " print(\"URL ne pointe pas vers une image.\")\n", 580 | "except requests.exceptions.RequestException as e:\n", 581 | " print(f\"Erreur lors du téléchargement : {e}\")\n" 582 | ] 583 | }, 584 | { 585 | "cell_type": "markdown", 586 | "metadata": {}, 587 | "source": [ 588 | "## Manipuler des images\n", 589 | "\n", 590 | "### La bibliothèque PIL\n", 591 | "\n", 592 | "#### Présentation de PIL/Pillow\n", 593 | "\n", 594 | "- **PIL** : Python Imaging Library, bibliothèque historique pour la manipulation d'images.\n", 595 | "- **Pillow** : Fork de PIL, activement maintenu et compatible avec les versions récentes de Python.\n", 596 | "\n", 597 | "Installation :\n", 598 | "\n", 599 | "```bash\n", 600 | "pip install Pillow\n", 601 | "```\n", 602 | "\n", 603 | "Importation :\n", 604 | "\n", 605 | "```python\n", 606 | "from PIL import Image\n", 607 | "```" 608 | ] 609 | }, 610 | { 611 | "cell_type": "markdown", 612 | "metadata": {}, 613 | "source": [ 614 | "### Manipulation de base d'une image\n", 615 | "\n", 616 | "#### Ouvrir et afficher une image" 617 | ] 618 | }, 619 | { 620 | "cell_type": "code", 621 | "execution_count": null, 622 | "metadata": {}, 623 | "outputs": [], 624 | "source": [ 625 | "from PIL import Image\n", 626 | "\n", 627 | "image = Image.open('PATHTODOWLOAD/image.jpg')\n", 628 | "image.show()" 629 | ] 630 | }, 631 | { 632 | "cell_type": "markdown", 633 | "metadata": {}, 634 | "source": [ 635 | "#### Redimensionner une image" 636 | ] 637 | }, 638 | { 639 | "cell_type": "code", 640 | "execution_count": null, 641 | "metadata": {}, 642 | "outputs": [], 643 | "source": [ 644 | "nouvelle_image = image.resize((800, 600))\n", 645 | "nouvelle_image.save('image_redimensionnee.jpg')" 646 | ] 647 | }, 648 | { 649 | "cell_type": "markdown", 650 | "metadata": {}, 651 | "source": [ 652 | "#### Rotation" 653 | ] 654 | }, 655 | { 656 | "cell_type": "code", 657 | "execution_count": null, 658 | "metadata": {}, 659 | "outputs": [], 660 | "source": [ 661 | "image_rotated = image.rotate(90)\n", 662 | "image_rotated.save('image_rotated.jpg')" 663 | ] 664 | }, 665 | { 666 | "cell_type": "markdown", 667 | "metadata": {}, 668 | "source": [ 669 | "#### Conversion de format" 670 | ] 671 | }, 672 | { 673 | "cell_type": "code", 674 | "execution_count": null, 675 | "metadata": {}, 676 | "outputs": [], 677 | "source": [ 678 | "image.convert('L').save('image_grayscale.jpg')" 679 | ] 680 | }, 681 | { 682 | "cell_type": "markdown", 683 | "metadata": {}, 684 | "source": [ 685 | "#### Recadrage" 686 | ] 687 | }, 688 | { 689 | "cell_type": "code", 690 | "execution_count": 31, 691 | "metadata": {}, 692 | "outputs": [], 693 | "source": [ 694 | "box = (200, 900, 2400, 3500) # (left, upper, right, lower)\n", 695 | "image_cropped = image.crop(box)\n", 696 | "image_cropped.save('image_cropped.jpg')" 697 | ] 698 | }, 699 | { 700 | "cell_type": "markdown", 701 | "metadata": {}, 702 | "source": [ 703 | "### Récupérer les données des images\n", 704 | "\n", 705 | "#### Accéder aux métadonnées\n", 706 | "\n", 707 | "Informations de base :" 708 | ] 709 | }, 710 | { 711 | "cell_type": "code", 712 | "execution_count": 32, 713 | "metadata": {}, 714 | "outputs": [ 715 | { 716 | "name": "stdout", 717 | "output_type": "stream", 718 | "text": [ 719 | "Format : JPEG\n", 720 | "Taille : (4872, 6496)\n", 721 | "Absoluter path : /Users/marioncharpier/Documents/Cours_ENC/Cours_6_Utilisation de l’API IIIF et manipulation de données 2/image.jpg\n" 722 | ] 723 | } 724 | ], 725 | "source": [ 726 | "print(f\"Format : {image.format}\")\n", 727 | "print(f\"Taille : {image.size}\")\n", 728 | "print(f\"Absoluter path : {image.filename}\")" 729 | ] 730 | }, 731 | { 732 | "cell_type": "markdown", 733 | "metadata": {}, 734 | "source": [ 735 | "---\n", 736 | "\n", 737 | "### Conclusion\n", 738 | "\n", 739 | "En maîtrisant ces bibliothèques et techniques, vous serez en mesure de :\n", 740 | "\n", 741 | "- Manipuler des données structurées (JSON).\n", 742 | "- Interagir avec le système de fichiers.\n", 743 | "- Télécharger des ressources en ligne de manière efficace et sécurisée.\n", 744 | "- Traiter et analyser des images pour vos projets en histoire numérique.\n", 745 | "\n", 746 | "Ces compétences sont essentielles pour analyser, conserver et diffuser le patrimoine historique dans le contexte numérique actuel.\n", 747 | "\n", 748 | "---\n", 749 | "\n", 750 | "Vous pouvez utiliser ce notebook comme base pour vos propres projets, en adaptant et en étendant les exemples fournis.\n", 751 | "\n", 752 | "---" 753 | ] 754 | } 755 | ], 756 | "metadata": { 757 | "kernelspec": { 758 | "display_name": "iiif_env", 759 | "language": "python", 760 | "name": "iiif_env" 761 | }, 762 | "language_info": { 763 | "codemirror_mode": { 764 | "name": "ipython", 765 | "version": 3 766 | }, 767 | "file_extension": ".py", 768 | "mimetype": "text/x-python", 769 | "name": "python", 770 | "nbconvert_exporter": "python", 771 | "pygments_lexer": "ipython3", 772 | "version": "3.8.0" 773 | } 774 | }, 775 | "nbformat": 4, 776 | "nbformat_minor": 2 777 | } 778 | -------------------------------------------------------------------------------- /Cours_6_Utilisation_IIIF_manipulation_données_2/Exercice_guide.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Exercice guidé : Télécharger des images depuis un manifeste IIIF\n", 8 | "\n", 9 | "Dans cet exercice, nous allons apprendre à télécharger des images à partir d'un manifeste IIIF en utilisant Python. Nous allons parcourir les étapes suivantes :\n", 10 | "\n", 11 | "1. **Ouvrir le manifeste**\n", 12 | "2. **Parcourir le manifeste pour trouver les URLs des images**\n", 13 | "3. **Utiliser la bibliothèque `requests` pour télécharger les images**\n", 14 | " - Afficher les codes de statut HTTP (200, 404, 429, etc.)\n", 15 | " - Récupérer les données\n", 16 | "4. **Construire le chemin d'enregistrement des images avec `os` et les enregistrer**\n", 17 | "5. **Utiliser la bibliothèque `PIL` pour enregistrer les caractéristiques de l'image dans un fichier `.txt` du même nom que l'image**\n", 18 | "6. **Automatiser le processus avec une fonction pour récupérer toutes les URLs du manifeste**\n", 19 | "\n", 20 | "---" 21 | ] 22 | }, 23 | { 24 | "cell_type": "markdown", 25 | "metadata": {}, 26 | "source": [ 27 | "## Prérequis\n", 28 | "\n", 29 | "Avant de commencer, assurez-vous d'avoir les bibliothèques Python suivantes installées :\n", 30 | "\n", 31 | "- `requests`\n", 32 | "- `Pillow` (PIL)\n", 33 | "\n", 34 | "Si vous travaillez sur colab activez la commande suivante dans une cellule python :\n", 35 | "```bash\n", 36 | "!pip install requests pillow\n", 37 | "```\n", 38 | "---" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "## Étape 1 : Ouvrir le manifeste\n", 46 | "\n", 47 | "Un manifeste IIIF est un fichier JSON qui décrit une ressource numérique complexe, telle qu'une collection d'images. Pour cet exercice, nous utiliserons un manifeste d'exemple." 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "import json\n", 57 | "import requests\n", 58 | "\n", 59 | "# URL du manifeste IIIF\n", 60 | "manifest_url = 'https://www.e-codices.unifr.ch/metadata/iiif/bbb-0318/manifest.json'\n", 61 | "\n", 62 | "# Télécharger le manifeste\n", 63 | "response = requests.get(manifest_url)\n", 64 | "\n", 65 | "# Vérifier que la requête s'est bien passée\n", 66 | "if response.status_code == 200:\n", 67 | " manifest = response.json()\n", 68 | " print(\"Manifeste chargé avec succès.\")\n", 69 | "else:\n", 70 | " print(f\"Erreur lors du chargement du manifeste : {response.status_code}\")" 71 | ] 72 | }, 73 | { 74 | "cell_type": "markdown", 75 | "metadata": {}, 76 | "source": [ 77 | "### Explications\n", 78 | "\n", 79 | "- **Importation des modules** : Nous importons les modules `json` pour manipuler le JSON et `requests` pour effectuer des requêtes HTTP.\n", 80 | "- **Téléchargement du manifeste** : Nous utilisons `requests.get()` pour envoyer une requête GET à l'URL du manifeste.\n", 81 | "- **Vérification du statut HTTP** : Nous vérifions si le `status_code` est 200, ce qui indique un succès.\n", 82 | "- **Chargement du manifeste** : Si la requête a réussi, nous chargeons le contenu JSON du manifeste en utilisant `response.json()`.\n", 83 | "\n", 84 | "---" 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "## Étape 2 : Parcourir le manifeste pour trouver les URLs des images\n", 92 | "\n", 93 | "Les images sont généralement situées dans les `canvases` du manifeste. Chaque canvas représente une image individuelle." 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": null, 99 | "metadata": {}, 100 | "outputs": [], 101 | "source": [ 102 | "# Extraire les canvases du manifeste\n", 103 | "canvases = manifest['sequences'][0]['canvases']\n", 104 | "\n", 105 | "# Créer une liste pour stocker les informations sur les images\n", 106 | "images_info = []\n", 107 | "\n", 108 | "# Parcourir les canvases pour extraire les informations\n", 109 | "for idx, canvas in enumerate(canvases):\n", 110 | " canvas_num = idx\n", 111 | " image_label = canvas['label'] # Récupère l'index (position) du canvas dans le manifeste\n", 112 | " image_url = canvas['images'][0]['resource']['@id']\n", 113 | " image_format = canvas['images'][0]['resource']['@id'].split('/')[-1]\n", 114 | " image_width_declared = canvas['images'][0]['resource']['width']\n", 115 | " image_height_declared = canvas['images'][0]['resource']['height']\n", 116 | " \n", 117 | " images_info.append({\n", 118 | " 'canvasNum': canvas_num,\n", 119 | " 'imageLabel': image_label,\n", 120 | " 'urlImage': image_url,\n", 121 | " 'imageFormat' : image_format,\n", 122 | " 'imageWidthAsDeclared': image_width_declared,\n", 123 | " 'imageHeightAsDeclared': image_height_declared\n", 124 | " })\n", 125 | "\n", 126 | "print(f\"Trouvé {len(images_info)} images dans le manifeste.\")" 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "### Explications\n", 134 | "\n", 135 | "- **Accès aux canvases** : Nous accédons à la liste des `canvases` du manifeste.\n", 136 | "- **Utilisation de `enumerate()`** : L'utilisation de `enumerate()` dans cette boucle a pour but de parcourir les canvas du manifeste tout en obtenant leur index (position) en plus de leur valeur (l'élément lui-même). C'est particulièrement utile pour contrer les problème de nommage que vous pouvez rencontrer dans certains manifestes où tous les médias on le même `label`, le plus souvent `NP`.\n", 137 | "\n", 138 | "- **Parcours des canvases** : Pour chaque canvas, nous extrayons :\n", 139 | " - `canvasNum` : Le numéro du canvas (son index).\n", 140 | " - `imageLabel` : Label de l'image, avec une valeur par défaut si absent.\n", 141 | " - `urlImage` : URL de l'image.\n", 142 | " - `imageFormat` : Le format de l'image (jpg, png, tiff, ...)\n", 143 | " - `imageWidthAsDeclared` et `imageHeightAsDeclared` : Dimensions déclarées de l'image.\n", 144 | "- **Stockage des informations** : Nous ajoutons ces informations à la liste `images_info`.\n", 145 | "\n", 146 | "\n", 147 | "\n", 148 | "---" 149 | ] 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "metadata": {}, 154 | "source": [ 155 | "## Étape 3 : Utiliser la bibliothèque `requests` pour télécharger les images\n", 156 | "\n", 157 | "Nous allons maintenant utiliser `requests` pour télécharger les images à partir des URLs que nous avons extraites. Nous afficherons également les codes de statut HTTP." 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": null, 163 | "metadata": {}, 164 | "outputs": [], 165 | "source": [ 166 | "# Importer les modules nécessaires\n", 167 | "import os\n", 168 | "\n", 169 | "# Créer un dossier pour stocker les images téléchargées\n", 170 | "folder_path = 'downloaded_images'\n", 171 | "if not os.path.exists(folder_path):\n", 172 | " os.makedirs(folder_path)\n", 173 | "\n", 174 | "# Parcourir la liste des images et les télécharger\n", 175 | "for idx, image in enumerate(images_info):\n", 176 | " url = image['urlImage']\n", 177 | " image_filename = f\"image_{idx+1}.jpg\"\n", 178 | " image_path = os.path.join(folder_path, image_filename)\n", 179 | " \n", 180 | " try:\n", 181 | " response = requests.get(url)\n", 182 | " html_code = response.status_code\n", 183 | " print(f\"Téléchargement de {image_filename} - Code HTTP : {html_code}\")\n", 184 | " \n", 185 | " if response.status_code == 200:\n", 186 | " # Enregistrer l'image sur le disque\n", 187 | " with open(image_path, 'wb') as file:\n", 188 | " file.write(response.content)\n", 189 | " image['imageFileName'] = image_filename\n", 190 | " image['folderPath'] = folder_path\n", 191 | " image['htmlCode'] = html_code\n", 192 | " else:\n", 193 | " print(f\"Erreur lors du téléchargement de l'image : {html_code}\")\n", 194 | " image['htmlCode'] = html_code\n", 195 | " except Exception as e:\n", 196 | " print(f\"Exception lors du téléchargement de l'image : {e}\")\n", 197 | " image['htmlCode'] = 'Exception'" 198 | ] 199 | }, 200 | { 201 | "cell_type": "markdown", 202 | "metadata": {}, 203 | "source": [ 204 | "### Explications\n", 205 | "\n", 206 | "- **Création du dossier** : Nous utilisons `os.makedirs()` pour créer un dossier `downloaded_images` si nécessaire.\n", 207 | "- **Téléchargement des images** :\n", 208 | " - Nous parcourons chaque image dans `images_info`.\n", 209 | " - Nous construisons le nom du fichier image.\n", 210 | " - Nous utilisons `requests.get()` pour télécharger l'image.\n", 211 | " - Nous affichons le code HTTP pour chaque requête.\n", 212 | " - Si le téléchargement est réussi (`status_code` 200), nous enregistrons l'image et mettons à jour les informations dans `images_info`.\n", 213 | " - Nous gérons les exceptions pour capturer les erreurs éventuelles.\n", 214 | "\n", 215 | "---" 216 | ] 217 | }, 218 | { 219 | "cell_type": "markdown", 220 | "metadata": {}, 221 | "source": [ 222 | "## Étape 4 : Construire le chemin d'enregistrement avec `os` et enregistrer l'image\n", 223 | "\n", 224 | "Nous avons déjà utilisé `os` pour créer le dossier et construire le chemin du fichier. Nous allons continuer à utiliser `os` pour assurer la portabilité du code." 225 | ] 226 | }, 227 | { 228 | "cell_type": "markdown", 229 | "metadata": {}, 230 | "source": [ 231 | "### Code\n", 232 | "\n", 233 | "*Cette étape est intégrée dans le code de l'étape précédente.*\n", 234 | "\n", 235 | "### Explications\n", 236 | "\n", 237 | "- **Construction du chemin du fichier** : Nous utilisons `os.path.join()` pour créer un chemin compatible avec le système d'exploitation.\n", 238 | "- **Vérification de l'existence du dossier** : `os.path.exists()` vérifie si le dossier existe déjà.\n", 239 | "- **Création du dossier** : `os.makedirs()` crée le dossier spécifié.\n", 240 | "\n", 241 | "---" 242 | ] 243 | }, 244 | { 245 | "cell_type": "markdown", 246 | "metadata": {}, 247 | "source": [ 248 | "## Étape 5 : Utiliser `PIL` pour enregistrer les caractéristiques de l'image\n", 249 | "\n", 250 | "Nous allons maintenant utiliser `PIL` pour ouvrir l'image téléchargée et obtenir ses dimensions réelles. Nous enregistrerons les caractéristiques de l'image dans un fichier `.txt` du même nom que l'image." 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": null, 256 | "metadata": {}, 257 | "outputs": [], 258 | "source": [ 259 | "from PIL import Image\n", 260 | "import os\n", 261 | "\n", 262 | "# Parcourir les images pour récupérer les caractéristiques et les enregistrer\n", 263 | "for image in images_info:\n", 264 | " image_filename = image.get('imageFileName')\n", 265 | " \n", 266 | " # Vérifier si l'image est valide (nom de fichier et code HTML = 200)\n", 267 | " if image_filename and image.get('htmlCode') == 200:\n", 268 | " image_path = os.path.join(image['folderPath'], image_filename)\n", 269 | " txt_filename = os.path.splitext(image_filename)[0] + '.txt'\n", 270 | " txt_path = os.path.join(image['folderPath'], txt_filename)\n", 271 | " \n", 272 | " # Ouvrir l'image avec PIL et récupérer les dimensions téléchargées (size retourne un tuple (width, height) )\n", 273 | " with Image.open(image_path) as img:\n", 274 | " image_width_downloaded, image_height_downloaded = img.size\n", 275 | " image['imageWidthAsDownloaded'] = image_width_downloaded\n", 276 | " image['imageHeightAsDownloaded'] = image_height_downloaded\n", 277 | " \n", 278 | " # Liste des clés à écrire dans le fichier .txt\n", 279 | " data_to_write = [\n", 280 | " 'imageFileName', 'canvasId', 'urlImage', 'folderPath', 'imageLabel',\n", 281 | " 'imageWidthAsDeclared', 'imageHeightAsDeclared', 'htmlCode',\n", 282 | " 'imageWidthAsDownloaded', 'imageHeightAsDownloaded'\n", 283 | " ]\n", 284 | " \n", 285 | " # Enregistrer les caractéristiques dans le fichier .txt\n", 286 | " with open(txt_path, 'w', encoding='utf-8') as txt_file:\n", 287 | " for key in data_to_write:\n", 288 | " value = image.get(key)\n", 289 | " # Si la valeur est nulle (None ou chaîne vide), remplacer par \"Non défini\"\n", 290 | " if not value:\n", 291 | " value = 'Non défini'\n", 292 | " txt_file.write(f\"{key}: {value}\\n\")\n", 293 | " \n", 294 | " print(f\"Caractéristiques enregistrées dans {txt_filename}\")\n", 295 | " else:\n", 296 | " print(f\"Image non téléchargée ou erreur lors du téléchargement pour {image.get('imageLabel', 'Inconnu')}\")\n" 297 | ] 298 | }, 299 | { 300 | "cell_type": "markdown", 301 | "metadata": {}, 302 | "source": [ 303 | "### Explications\n", 304 | "\n", 305 | "- **Ouverture de l'image avec PIL** : Nous utilisons `Image.open()` pour ouvrir l'image téléchargée.\n", 306 | "- **Récupération des dimensions** : `img.size` renvoie les dimensions réelles de l'image sous la forme d'un tuple largeur, hauteur.\n", 307 | "- **Création du fichier `.txt`** :\n", 308 | " - Nous changeons l'extension du nom de l'image en `.txt` en utilisant `os.path.splitext()`.\n", 309 | " - Nous écrivons les caractéristiques de l'image dans le fichier texte.\n", 310 | "- **Gestion des erreurs** : \n", 311 | " - Si l'image n'a pas été téléchargée avec succès, nous affichons un message.\n", 312 | " - Lors de l'écriture, si une clé est absente, une valeur par défaut sera retournée ('Non défini'). Cela évite les erreurs si certaines informations manquent.\n", 313 | "\n", 314 | "- **Attention** : Le `get()` auquel nous faisons référence pour `image.get('imageFileName')` est une méthode des dictionnaires Python, utilisée pour récupérer la valeur associée à une clé spécifique dans un dictionnaire. Si la clé n'existe pas, `get()` retourne `None` (ou une valeur par défaut si spécifiée), ce qui évite de lever une exception (`KeyError`) comme avec l'accès direct par [].\n", 315 | "---" 316 | ] 317 | }, 318 | { 319 | "cell_type": "markdown", 320 | "metadata": {}, 321 | "source": [ 322 | "## Étape 6 : Automatiser le processus avec une fonction\n", 323 | "\n", 324 | "Pour rendre le processus réutilisable, vous allez encapsuler le code dans une fonction qui prend en entrée l'URL du manifeste et le dossier chemin vers le dossier de téléchargement." 325 | ] 326 | }, 327 | { 328 | "cell_type": "code", 329 | "execution_count": null, 330 | "metadata": {}, 331 | "outputs": [], 332 | "source": [ 333 | "# Votre code ici" 334 | ] 335 | }, 336 | { 337 | "cell_type": "markdown", 338 | "metadata": {}, 339 | "source": [ 340 | "### Explications\n", 341 | "\n", 342 | "- **Définition de la fonction** : `download_images_from_manifest()` prend en entrée l'URL du manifeste et le nom du dossier de destination.\n", 343 | "- **Réutilisation du code** : L'objectif est d'encapsuler le code des étapes précédentes dans la fonction.\n", 344 | "- **Appel de la fonction** : N'oubliez pas d'appeler la fonction!\n", 345 | "\n", 346 | "---" 347 | ] 348 | }, 349 | { 350 | "cell_type": "markdown", 351 | "metadata": {}, 352 | "source": [ 353 | "## Conclusion\n", 354 | "\n", 355 | "Dans cet exercice, nous avons appris à :\n", 356 | "\n", 357 | "- **Ouvrir et analyser un manifeste IIIF** pour extraire les URLs des images.\n", 358 | "- **Utiliser la bibliothèque `requests`** pour télécharger les images et gérer les codes de statut HTTP.\n", 359 | "- **Utiliser la bibliothèque `os`** pour construire les chemins d'enregistrement et gérer les fichiers.\n", 360 | "- **Utiliser la bibliothèque `PIL`** pour obtenir les caractéristiques des images téléchargées.\n", 361 | "- **Automatiser le processus avec une fonction** pour le rendre réutilisable.\n", 362 | "\n", 363 | "Ces compétences sont essentielles pour manipuler des ressources numériques dans le domaine de l'histoire numérique et pour gérer efficacement des collections d'images.\n", 364 | "\n", 365 | "---\n", 366 | "\n", 367 | "**Remarque** : Assurez-vous d'avoir une connexion Internet active lors de l'exécution de ce notebook, car il nécessite de télécharger des données en ligne.\n", 368 | "\n", 369 | "---" 370 | ] 371 | }, 372 | { 373 | "cell_type": "markdown", 374 | "metadata": {}, 375 | "source": [ 376 | "# Exécution du notebook\n", 377 | "\n", 378 | "Vous pouvez maintenant exécuter ce notebook cellule par cellule pour tester le processus complet de téléchargement d'images depuis un manifeste IIIF.\n", 379 | "\n", 380 | "**Bon courage !**" 381 | ] 382 | } 383 | ], 384 | "metadata": { 385 | "kernelspec": { 386 | "display_name": "iiif_env", 387 | "language": "python", 388 | "name": "iiif_env" 389 | }, 390 | "language_info": { 391 | "codemirror_mode": { 392 | "name": "ipython", 393 | "version": 3 394 | }, 395 | "file_extension": ".py", 396 | "mimetype": "text/x-python", 397 | "name": "python", 398 | "nbconvert_exporter": "python", 399 | "pygments_lexer": "ipython3", 400 | "version": "3.8.0" 401 | } 402 | }, 403 | "nbformat": 4, 404 | "nbformat_minor": 2 405 | } 406 | -------------------------------------------------------------------------------- /Cours_6_Utilisation_IIIF_manipulation_données_2/Séance 6 - Introduction à IIIF et à la manipulation de fichiers 2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaouabti/Cours_ENC_Introduction_programmation_Python/7dce58e731a47ba702bba33e292090c8b1e7612d/Cours_6_Utilisation_IIIF_manipulation_données_2/Séance 6 - Introduction à IIIF et à la manipulation de fichiers 2.pdf -------------------------------------------------------------------------------- /Evaluation/Correction_evaluation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Correction de l'Examen : Introduction à la programmation en Python\n", 8 | "\n", 9 | "---\n", 10 | "\n", 11 | "## **Partie 1 : QCM**\n", 12 | "\n", 13 | "### **1. Quel type de données est renvoyé par la fonction `len()` lorsqu'elle est appliquée à une liste ?**\n", 14 | "\n", 15 | "**Réponse :**\n", 16 | "\n", 17 | "**a) Integer**\n", 18 | "\n", 19 | "**Explication :** La fonction `len()` retourne un entier représentant le nombre d'éléments dans la liste.\n", 20 | "\n", 21 | "---\n", 22 | "\n", 23 | "### **2. Quelle méthode permet d'ajouter un élément à la fin d'une liste en Python ?**\n", 24 | "\n", 25 | "**Réponse :**\n", 26 | "\n", 27 | "**b) `append()`**\n", 28 | "\n", 29 | "**Explication :** La méthode `append()` ajoute un élément à la fin d'une liste existante.\n", 30 | "\n", 31 | "---\n", 32 | "\n", 33 | "### **3. Considérez la liste suivante :**\n", 34 | "\n", 35 | "```python\n", 36 | "animals = ['draco', 'scitalis', 'amphisbena', 'basilisk', 'panthera', 'lion']\n", 37 | "```\n", 38 | "\n", 39 | "**Quelle(s) commande(s) permet(tent) d'afficher `['draco', 'scitalis', 'amphisbena']` ?**\n", 40 | "\n", 41 | "**Réponses :**\n", 42 | "\n", 43 | "**b) `print(animals[0:3])` \n", 44 | "d) `print(animals[:-3])`**\n", 45 | "\n", 46 | "**Explication :**\n", 47 | "\n", 48 | "- `animals[0:3]` sélectionne les éléments aux indices 0, 1 et 2.\n", 49 | "- `animals[:-3]` sélectionne tous les éléments depuis le début jusqu'à l'indice -3 (exclu), soit les trois premiers éléments.\n", 50 | "\n", 51 | "---\n", 52 | "\n", 53 | "### **4. Quel est le résultat de l'expression `'Python' + '3'` ?**\n", 54 | "\n", 55 | "**Réponse :**\n", 56 | "\n", 57 | "**a) `'Python3'`**\n", 58 | "\n", 59 | "**Explication :** L'opérateur `+` concatène les chaînes de caractères, donc `'Python' + '3'` donne `'Python3'`.\n", 60 | "\n", 61 | "---\n", 62 | "\n", 63 | "### **5. Quelle est la syntaxe correcte pour définir une fonction en Python ?**\n", 64 | "\n", 65 | "**Réponse :**\n", 66 | "\n", 67 | "**c) `def ma_fonction():`**\n", 68 | "\n", 69 | "**Explication :** En Python, une fonction est définie en utilisant le mot-clé `def` suivi du nom de la fonction et de parenthèses, puis d'un deux-points.\n", 70 | "\n", 71 | "---\n", 72 | "\n", 73 | "### **6. Laquelle des options suivantes est une fonction anonyme en Python ?**\n", 74 | "\n", 75 | "**Réponse :**\n", 76 | "\n", 77 | "**b) `lambda x: x * 2`**\n", 78 | "\n", 79 | "**Explication :** Les fonctions anonymes en Python sont définies à l'aide du mot-clé `lambda`.\n", 80 | "\n", 81 | "---\n", 82 | "\n", 83 | "### **7. Que fait la méthode `split()` lorsqu'elle est appliquée à une chaîne de caractères ?**\n", 84 | "\n", 85 | "**Réponse :**\n", 86 | "\n", 87 | "**b) Elle divise la chaîne en une liste.**\n", 88 | "\n", 89 | "**Explication :** La méthode `split()` sépare une chaîne de caractères en une liste de sous-chaînes en fonction d'un séparateur.\n", 90 | "\n", 91 | "---\n", 92 | "\n", 93 | "### **8. Dans le contexte de la programmation orientée objet, que représente le mot-clé `self` dans une méthode ?**\n", 94 | "\n", 95 | "**Réponse :**\n", 96 | "\n", 97 | "**b) L'instance actuelle de la classe.**\n", 98 | "\n", 99 | "**Explication :** `self` fait référence à l'instance sur laquelle la méthode est appelée, permettant d'accéder aux attributs et méthodes de la classe.\n", 100 | "\n", 101 | "---\n", 102 | "\n", 103 | "### **9. Quelle est la syntaxe correcte pour vérifier si un fichier existe en utilisant le module `os` ?**\n", 104 | "\n", 105 | "**Réponse :**\n", 106 | "\n", 107 | "**a) `os.path.isfile('chemin/vers/fichier')` \n", 108 | "c) `os.path.exists('chemin/vers/fichier')`**\n", 109 | "\n", 110 | "**Explication :** La fonction `os.path.isfile()` vérifie spécifiquement si un chemin correspond à un fichier existant.\n", 111 | "\n", 112 | "**Explication:** La fonction `os.path.exists()` vérifie si le chemin existe, qu'il pointe vers un fichier, un répertoire ou un lien symbolique. Elle peut être utilisée pour vérifier l'existence d'un fichier, mais elle retournera également `True` si le chemin est un répertoire.\n", 113 | "\n", 114 | "---\n", 115 | "\n", 116 | "### **10. À quoi servent `*args` et `**kwargs` dans une fonction Python ?**\n", 117 | "\n", 118 | "**Réponse :**\n", 119 | "\n", 120 | "**c) `*args` permet de passer un nombre variable d'arguments positionnels, et `**kwargs` un nombre variable d'arguments nommés.**\n", 121 | "\n", 122 | "**Explication :**\n", 123 | "\n", 124 | "- `*args` capture les arguments positionnels supplémentaires sous forme de tuple.\n", 125 | "- `**kwargs` capture les arguments nommés supplémentaires sous forme de dictionnaire.\n", 126 | "\n", 127 | "---\n", 128 | "\n", 129 | "### **11. Que renvoie la méthode `keys()` lorsqu'elle est appliquée à un dictionnaire ?**\n", 130 | "\n", 131 | "**Réponse :**\n", 132 | "\n", 133 | "**c) Une liste des clés du dictionnaire.**\n", 134 | "\n", 135 | "**Explication :** La méthode `keys()` renvoie une vue contenant toutes les clés du dictionnaire.\n", 136 | "\n", 137 | "---\n", 138 | "\n", 139 | "### **12. Quelle fonction permet de convertir et sauvegarder le dictionnaire suivant dans un fichier JSON ?**\n", 140 | "\n", 141 | "```python\n", 142 | "film = {\n", 143 | " \"titre\": \"Häxan. La Sorcellerie à travers les âges\",\n", 144 | " \"annee\": 1922,\n", 145 | " \"realisateur\": \"Benjamin Christensen\",\n", 146 | " \"suite\": False,\n", 147 | " \"personnages_principaux\": [\n", 148 | " {\"nom\": \"Sorcière\", \"acteur\": \"Maren Pedersen\"},\n", 149 | " {\"nom\": \"Le Diable\", \"acteur\": \"Benjamin Christensen\"}\n", 150 | " ],\n", 151 | " \"genres\": [\"Horreur\", \"Classique\"]\n", 152 | "}\n", 153 | "```\n", 154 | "\n", 155 | "**Réponse :**\n", 156 | "\n", 157 | "**c) `json.dump(film)`**\n", 158 | "\n", 159 | "**Explication :** La fonction `json.dump()` est utilisée pour écrire un objet Python dans un fichier au format JSON.\n" 160 | ] 161 | }, 162 | { 163 | "cell_type": "markdown", 164 | "metadata": {}, 165 | "source": [ 166 | "---\n", 167 | "\n", 168 | "## **Partie 2 : Exercices**\n", 169 | "\n", 170 | "### **Exercice 1 : Fonctions et Boucles**\n", 171 | "\n", 172 | "**Sujet :**\n", 173 | "\n", 174 | "Écrivez une fonction nommée `calculer_moyenne` qui :\n", 175 | "\n", 176 | "- Prend en paramètre une **liste de nombres**.\n", 177 | "- Renvoie la **moyenne** de ces nombres.\n", 178 | "- Si la liste est vide, la fonction doit renvoyer `None`.\n", 179 | "- Utilisez une boucle `for` pour parcourir la liste.\n", 180 | "- **Commentez** votre code pour expliquer votre démarche.\n", 181 | "\n", 182 | "**Correction :**" 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "execution_count": 1, 188 | "metadata": {}, 189 | "outputs": [ 190 | { 191 | "name": "stdout", 192 | "output_type": "stream", 193 | "text": [ 194 | "30.0\n" 195 | ] 196 | } 197 | ], 198 | "source": [ 199 | "def calculer_moyenne(nombres):\n", 200 | " # Vérifier si la liste est vide\n", 201 | " if not nombres:\n", 202 | " return None\n", 203 | " # Initialiser la somme des nombres à zéro\n", 204 | " somme = 0\n", 205 | " # Parcourir chaque nombre dans la liste\n", 206 | " for nombre in nombres:\n", 207 | " somme += nombre # Ajouter le nombre à la somme\n", 208 | " # Calculer la moyenne en divisant la somme par le nombre d'éléments\n", 209 | " moyenne = somme / len(nombres)\n", 210 | " # Retourner la moyenne calculée\n", 211 | " return moyenne\n", 212 | "\n", 213 | "# Exemple d'utilisation\n", 214 | "liste_nombres = [10, 20, 30, 40, 50]\n", 215 | "print(calculer_moyenne(liste_nombres)) # Affiche 30.0" 216 | ] 217 | }, 218 | { 219 | "cell_type": "markdown", 220 | "metadata": {}, 221 | "source": [ 222 | "**Explications :**\n", 223 | "\n", 224 | "- **Vérification de la liste vide :** Avant de procéder au calcul, on vérifie si la liste `nombres` est vide pour éviter une division par zéro.\n", 225 | "- **Initialisation de la somme :** On initialise une variable `somme` à zéro pour accumuler les valeurs.\n", 226 | "- **Boucle `for` :** On parcourt chaque élément de la liste et on ajoute sa valeur à `somme`.\n", 227 | "- **Calcul de la moyenne :** On divise la `somme` totale par le nombre d'éléments dans la liste en utilisant `len(nombres)`.\n", 228 | "- **Retour de la moyenne :** La fonction renvoie la valeur calculée de la moyenne.\n", 229 | "\n", 230 | "---" 231 | ] 232 | }, 233 | { 234 | "cell_type": "markdown", 235 | "metadata": {}, 236 | "source": [ 237 | "### **Exercice 2 : Manipulation de Fichiers et du Module `os`**\n", 238 | "\n", 239 | "**Sujet :**\n", 240 | "\n", 241 | "Écrivez un script qui :\n", 242 | "\n", 243 | "1. **Demande** à l'utilisateur de saisir un chemin de répertoire.\n", 244 | "\n", 245 | "2. **Vérifie** si le répertoire existe en utilisant `os.path.exists`.\n", 246 | "\n", 247 | " - S'il n'existe pas, **le crée** en utilisant `os.makedirs` avec `exist_ok=True`.\n", 248 | "\n", 249 | "3. **Liste** tous les fichiers du répertoire en utilisant `os.listdir` et **affiche** uniquement les fichiers qui ont l'extension `.txt`.\n", 250 | "\n", 251 | "4. Pour chaque fichier .txt, **ouvre** le fichier, **lit** son contenu, et **affiche** le nombre de lignes qu'il contient.\n", 252 | "\n", 253 | "**Correction :**" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": null, 259 | "metadata": {}, 260 | "outputs": [], 261 | "source": [ 262 | "import os\n", 263 | "\n", 264 | "# 1. Demande à l'utilisateur de saisir un chemin de répertoire\n", 265 | "chemin = input(\"Entrez le chemin du répertoire (laisser vide pour le répertoire courant) : \")\n", 266 | "\n", 267 | "# Utiliser le répertoire courant si aucun chemin n'est fourni\n", 268 | "if not chemin:\n", 269 | " chemin = os.getcwd()\n", 270 | "\n", 271 | "# 2. Vérifie si le répertoire existe\n", 272 | "if not os.path.exists(chemin):\n", 273 | " # Le crée s'il n'existe pas\n", 274 | " os.makedirs(chemin, exist_ok=True)\n", 275 | " print(f\"Le répertoire '{chemin}' a été créé.\")\n", 276 | "else:\n", 277 | " print(f\"Le répertoire '{chemin}' existe déjà.\")\n", 278 | "\n", 279 | "# 3. Liste tous les fichiers du répertoire et affiche uniquement les fichiers .txt\n", 280 | " fichiers = os.listdir(chemin)\n", 281 | " fichiers_txt = [f for f in fichiers if f.endswith('.txt')]\n", 282 | " print(\"Fichiers .txt trouvés :\")\n", 283 | " for fichier in fichiers_txt:\n", 284 | " print(fichier)\n", 285 | "\n", 286 | "# 4. Pour chaque fichier .txt, ouvre le fichier, lit son contenu, et affiche le nombre de lignes\n", 287 | "\n", 288 | "for fichier in fichiers_txt:\n", 289 | " chemin_complet = os.path.join(chemin, fichier)\n", 290 | " try:\n", 291 | " lignes = []\n", 292 | " with open(chemin_complet, 'r', encoding='utf-8') as f:\n", 293 | " for line in f:\n", 294 | " lignes.append(line)\n", 295 | " print(f\"Le fichier '{fichier}' contient {len(lignes)} lignes.\")\n", 296 | " except Exception as e:\n", 297 | " print(f\"Impossible de lire le fichier '{fichier}' : {e}\")" 298 | ] 299 | }, 300 | { 301 | "cell_type": "markdown", 302 | "metadata": {}, 303 | "source": [ 304 | "**Explications :**\n", 305 | "\n", 306 | "- **Importation du module `os` :** Nécessaire pour les opérations sur le système de fichiers.\n", 307 | "- **Saisie du chemin :** On demande à l'utilisateur d'entrer un chemin ou on utilise le répertoire courant avec `os.getcwd()`.\n", 308 | "- **Vérification de l'existence du répertoire :** Utilisation de `os.path.exists()` pour vérifier si le répertoire existe.\n", 309 | "- **Création du répertoire :** Si le répertoire n'existe pas, on le crée avec `os.makedirs()` en utilisant `exist_ok=True` pour éviter les erreurs si le répertoire existe déjà.\n", 310 | "- **Liste des fichiers :**\n", 311 | " - Utilisation de `os.listdir()` pour obtenir la liste des fichiers.\n", 312 | " - Filtrage des fichiers pour ne garder que ceux qui se terminent par `.txt`.\n", 313 | "- **Affichage des fichiers `.txt` :** Impression des noms des fichiers trouvés.\n", 314 | "- **Lecture des fichiers :**\n", 315 | " - Initialisation de la liste de ligne pour chaque fichier\n", 316 | " - Pour chaque fichier `.txt`, ouverture en mode lecture.\n", 317 | " - Lecture des lignes avec un boucle `for`.\n", 318 | " - Comptage et affichage du nombre de lignes.\n", 319 | "- **Gestion des exceptions :**\n", 320 | " - Utilisation de `try...except` pour gérer les erreurs potentielles lors de la lecture du répertoire ou des fichiers.\n", 321 | "\n", 322 | "---" 323 | ] 324 | }, 325 | { 326 | "cell_type": "markdown", 327 | "metadata": {}, 328 | "source": [ 329 | "### **Exercice 3 : Programmation Orientée Objet**\n", 330 | "\n", 331 | "**Sujet :**\n", 332 | "\n", 333 | "**Création de la classe de base Monument :**\n", 334 | "\n", 335 | "1. Créez une classe nommée Monument avec les attributs suivants :\n", 336 | "\n", 337 | " - nom (chaîne de caractères)\n", 338 | " - ville (chaîne de caractères)\n", 339 | " - annee_construction (entier)\n", 340 | " - description (chaîne de caractères)\n", 341 | "\n", 342 | "2. La classe doit inclure :\n", 343 | "\n", 344 | " - Une méthode `caracteristiques` qui affiche les renseignements de base du monument.\n", 345 | "\n", 346 | "**Création de la classe dérivée Chateau :**\n", 347 | "\n", 348 | "3. Créez une classe Chateau qui hérite de la classe Monument et qui ajoute les attributs supplémentaires suivants :\n", 349 | "\n", 350 | " - style_architectural (chaîne de caractères)\n", 351 | " - classement_unesco (booléen)\n", 352 | "\n", 353 | "4. La classe Chateau doit inclure :\n", 354 | "\n", 355 | " - Une méthode `caracteristiques` qui affiche les renseignements de la classe parent et les siens.\n", 356 | "\n", 357 | "**Instanciation et utilisation :**\n", 358 | "\n", 359 | "5. Instanciez un objet de la classe Chateau pour le Château de Versailles avec les informations suivantes :\n", 360 | "\n", 361 | " - Nom : \"Château de Versailles\"\n", 362 | " - Ville : \"Versailles\"\n", 363 | " - Année de construction : 1623\n", 364 | " - Description : \"Ancienne résidence royale française.\"\n", 365 | " - Style architectural : \"Baroque\"\n", 366 | " - Classement UNESCO : True\n", 367 | "\n", 368 | "6. **Appelez** la méthode caracteristiques pour afficher les informations du château.\n", 369 | "\n", 370 | "**Correction :**" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": null, 376 | "metadata": {}, 377 | "outputs": [], 378 | "source": [ 379 | "# Définition de la classe de base Monument\n", 380 | "class Monument:\n", 381 | " def __init__(self, nom, ville, annee_construction, description):\n", 382 | " # Initialisation des attributs\n", 383 | " self.nom = nom\n", 384 | " self.ville = ville\n", 385 | " self.annee_construction = annee_construction\n", 386 | " self.description = description\n", 387 | "\n", 388 | " def caracteristiques(self):\n", 389 | " # Affichage des informations de base du monument\n", 390 | " print(f\"Nom : {self.nom}\")\n", 391 | " print(f\"Ville : {self.ville}\")\n", 392 | " print(f\"Année de construction : {self.annee_construction}\")\n", 393 | " print(f\"Description : {self.description}\")\n", 394 | "\n", 395 | "# Classe Chateau qui hérite de Monument\n", 396 | "class Chateau(Monument):\n", 397 | " def __init__(self, nom, ville, annee_construction, description, style_architectural, classement_unesco):\n", 398 | " # Appel du constructeur de la classe parent\n", 399 | " super().__init__(nom, ville, annee_construction, description)\n", 400 | " # Initialisation des attributs spécifiques à Chateau\n", 401 | " self.style_architectural = style_architectural\n", 402 | " self.classement_unesco = classement_unesco\n", 403 | "\n", 404 | " def caracteristiques(self):\n", 405 | " # Appel de la méthode caracteristiques de la classe parent\n", 406 | " super().caracteristiques()\n", 407 | " # Affichage des attributs spécifiques à Chateau\n", 408 | " print(f\"Style architectural : {self.style_architectural}\")\n", 409 | " print(f\"Classé UNESCO : {'Oui' if self.classement_unesco else 'Non'}\")" 410 | ] 411 | }, 412 | { 413 | "cell_type": "code", 414 | "execution_count": null, 415 | "metadata": {}, 416 | "outputs": [], 417 | "source": [ 418 | "# Instanciation du Château de Versailles\n", 419 | "chateau_versailles = Chateau(\n", 420 | " nom=\"Château de Versailles\",\n", 421 | " ville=\"Versailles\",\n", 422 | " annee_construction=1623,\n", 423 | " description=\"Ancienne résidence royale française.\",\n", 424 | " style_architectural=\"Baroque\",\n", 425 | " classement_unesco=True\n", 426 | ")\n", 427 | "\n", 428 | "# Appel de la méthode caracteristiques\n", 429 | "chateau_versailles.caracteristiques()" 430 | ] 431 | }, 432 | { 433 | "cell_type": "markdown", 434 | "metadata": {}, 435 | "source": [ 436 | "**Explications :**\n", 437 | "\n", 438 | "- **Classe `Monument` :**\n", 439 | " - Le constructeur `__init__` initialise les attributs de base.\n", 440 | " - La méthode `caracteristiques` affiche les informations du monument.\n", 441 | "- **Classe `Chateau` :**\n", 442 | " - Hérite de `Monument` et ajoute deux attributs supplémentaires.\n", 443 | " - Le constructeur utilise `super()` pour appeler le constructeur de la classe parent.\n", 444 | " - La méthode `caracteristiques` surcharge celle de la classe parent pour ajouter les nouvelles informations.\n", 445 | "- **Instanciation :**\n", 446 | " - Création d'un objet `chateau_versailles` avec les informations fournies.\n", 447 | " - Appel de `caracteristiques` pour afficher toutes les informations du château.\n", 448 | "\n", 449 | "---" 450 | ] 451 | } 452 | ], 453 | "metadata": { 454 | "kernelspec": { 455 | "display_name": "iiif_env", 456 | "language": "python", 457 | "name": "iiif_env" 458 | }, 459 | "language_info": { 460 | "codemirror_mode": { 461 | "name": "ipython", 462 | "version": 3 463 | }, 464 | "file_extension": ".py", 465 | "mimetype": "text/x-python", 466 | "name": "python", 467 | "nbconvert_exporter": "python", 468 | "pygments_lexer": "ipython3", 469 | "version": "3.8.0" 470 | } 471 | }, 472 | "nbformat": 4, 473 | "nbformat_minor": 2 474 | } 475 | -------------------------------------------------------------------------------- /Evaluation/Evaluation_python_20241104.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chaouabti/Cours_ENC_Introduction_programmation_Python/7dce58e731a47ba702bba33e292090c8b1e7612d/Evaluation/Evaluation_python_20241104.pdf --------------------------------------------------------------------------------