{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Les boucles en python\n",
        "\n",
        "Matthieu Falce  \n",
        "2023-11-21\n",
        "\n",
        "## Intérêt\n",
        "\n",
        "Imaginez que vous êtes un élève qui à une punition. Vous devez écrire un\n",
        "programme qui affiche 100 fois “Je n’utiliserai plus ChatGPT pour faire\n",
        "mes exercices”.\n",
        "\n",
        "Si vous n’utilisez pas de boucles, vous devriez faire quelque chose\n",
        "comme ça :\n",
        "\n",
        "``` python\n",
        "print(\"Je n'utiliserai plus ChatGPT pour faire mes exercices\")\n",
        "print(\"Je n'utiliserai plus ChatGPT pour faire mes exercices\")\n",
        "print(\"Je n'utiliserai plus ChatGPT pour faire mes exercices\")\n",
        "... # répété pleins de fois\n",
        "print(\"Je n'utiliserai plus ChatGPT pour faire mes exercices\")\n",
        "```\n",
        "\n",
        "En pratique, vous avez une tâche qui se répète de nombreuses fois et\n",
        "vous voulez l’automatiser. Cela vous permettra de vous concentrer sur le\n",
        "contenu de la tâche.\n",
        "\n",
        "## Cas d’usage\n",
        "\n",
        "Voici quelques autres cas où nous pouvons rencontrer des boucles. Il\n",
        "s’agit d’un concept fondamental donc, ce n’est qu’une liste non\n",
        "exhaustive, en pratique vous en manipulerai quasiment en permanence.\n",
        "\n",
        "-   traitement de conteneurs (listes) :\n",
        "    -   disons que vous gérez une liste de noms et que vous voulez\n",
        "        imprimer chacun d’entre eux sur l’écran.\n",
        "    -   avec une boucle, vous pouvez parcourir la liste et imprimer\n",
        "        chaque nom sans avoir à écrire une ligne de code pour chaque\n",
        "        nom.\n",
        "-   jeux vidéo :\n",
        "    -   dans les jeux vidéo, les boucles sont utilisées pour\n",
        "        continuellement vérifier les entrées des joueurs, mettre à jour\n",
        "        les graphiques à l’écran, et contrôler les interactions dans le\n",
        "        jeu.\n",
        "    -   sans boucles, vos personnages pourraient ne pas répondre lorsque\n",
        "        vous appuyez sur un bouton !\n",
        "-   sites Web :\n",
        "    -   quand vous faites défiler votre fil d’actualité sur les réseaux\n",
        "        sociaux, une boucle est utilisée pour charger et afficher de\n",
        "        nouveaux contenus automatiquement à mesure que vous atteignez le\n",
        "        bas de la page.\n",
        "-   traitement de données :\n",
        "    -   pour les scientifiques de données, les boucles permettent de\n",
        "        traiter de grands ensembles de données, en exécutant des\n",
        "        analyses ou des transformations sur chaque élément de\n",
        "        l’ensemble, comme calculer la moyenne des températures sur une\n",
        "        année.\n",
        "-   automatisation de tâches répétitives :\n",
        "    -   supposons que vous avez un ensemble de fichiers et que vous\n",
        "        voulez renommer chacun d’eux ou en extraire certaines\n",
        "        informations.\n",
        "    -   les boucles peuvent exécuter ces opérations sur chaque fichier\n",
        "        en succession sans intervention manuelle.\n",
        "\n",
        "Dans tous ces cas, nous remarquons que nous voulons exécuter une tâche\n",
        "plusieurs fois en parcourant des données ou en attendant un critère\n",
        "d’arrêt. C’est aussi exactement ce que l’on veut faire pour optimiser\n",
        "l’écriture de notre punition.\n",
        "\n",
        "Mais avant cela, nous devons regarder un peu plus de théorie.\n",
        "\n",
        "## Types de boucles\n",
        "\n",
        "Les langages de programmation (pas que Python) proposent souvent des\n",
        "boucles. Et nous en avons plusieurs types. Les plus connues, et que nous\n",
        "avons en python, sont les boucles `for` et les `while`.\n",
        "\n",
        "Leurs points commun principal est que les deux vont définir un **bloc**\n",
        "représentant la partie de logique à répéter. Nous allons donc avoir :\n",
        "\n",
        "-   un mot clé (`for` ou `while`)\n",
        "-   des paramètres\n",
        "-   le caractères `:`\n",
        "-   l’intérieur du bloc qui est indenté\n",
        "-   une *désindantation* qui marque la fin du bloc\n",
        "\n",
        "Nous allons voir leurs spécificités dans les parties suivantes.\n",
        "\n",
        "### Boucles `for`\n",
        "\n",
        "La boucle `for` (**pour** en anglais) permet de répéter une action **un\n",
        "certain nombre de fois**. On l’utilise quand on connaît à l’avance le\n",
        "nombre d’itérations à effectuer. C’est celle que vous allez utiliser le\n",
        "plus souvent, par exemple elle permet d’exprimer les concepts suivants :\n",
        "\n",
        "-   avancer de 10 pas dans la rue\n",
        "-   pelez 10 carottes…\n",
        "\n",
        "Imaginons que nous voulions répéter 5 fois la phrase de punition en\n",
        "affichant le numéro d’itération, nous ferions :"
      ],
      "id": "730310d1-8572-4a09-a96d-0f76e0189fbe"
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {},
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "iteration : 0 -- Je n'utiliserai plus ChatGPT pour faire mes exercices\n",
            "iteration : 1 -- Je n'utiliserai plus ChatGPT pour faire mes exercices\n",
            "iteration : 2 -- Je n'utiliserai plus ChatGPT pour faire mes exercices\n",
            "iteration : 3 -- Je n'utiliserai plus ChatGPT pour faire mes exercices\n",
            "iteration : 4 -- Je n'utiliserai plus ChatGPT pour faire mes exercices"
          ]
        }
      ],
      "source": [
        "for index in range(5):\n",
        "    print(\"iteration :\", index, \"--\", \"Je n'utiliserai plus ChatGPT pour faire mes exercices\")"
      ],
      "id": "7bddc5e7-e567-49e6-a467-06bca9890f5a"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "On est passé de 100 lignes à réécrire à 2. Plutôt pratique.\n",
        "\n",
        "Pour comprendre ce bout de code, nous devons le décomposer :\n",
        "\n",
        "-   `for index in range(5)` :\n",
        "    -   le `for ... in` est le mot clé permettant de déclarer la boucle,\n",
        "        elle va parcourir ce qui est à droite du `in`  \n",
        "    -   `range(5)` est une fonction permettant de générer les nombres de\n",
        "        0 à 4\n",
        "    -   `index` défini le nom de la variable qui va contenir les\n",
        "        variables récupérées lors du parcours du range\n",
        "-   le corps de la boucle\n",
        "    -   `index` permet d’accéder au contenu de la variable `index`. Dans\n",
        "        notre cas elle va contenir les nombre de 0 à 4 successivement\n",
        "    -   le reste permet d’afficher la chaîne de caractère\n",
        "\n",
        "On peut imaginer la boucle `for` comme un mécanisme permettant de\n",
        "tourner les pages d’un livre et d’effectuer une action sur chaque page.\n",
        "Dans notre cas, le livre représente le `range`, les pages sont contenues\n",
        "dans `index` et l’intérieur du bloc représente l’opération à effectuer\n",
        "sur la page en cours (la valeur de `index`).\n",
        "\n",
        "### Boucles `while`\n",
        "\n",
        "La boucle `while` (**tant que** en anglais) permet de répéter une action\n",
        "**jusqu’à une arriver à une certaine condition**. On l’utilise quand on\n",
        "ne connaît pas à l’avance le nombre d’itérations à effectuer. Elle est\n",
        "plus rare à utiliser (en tout cas je l’utilise bien moins souvent). Elle\n",
        "permet d’exprimer les concepts suivants dans la vie de tous les jours :\n",
        "\n",
        "-   attendre que l’eau bouille\n",
        "-   marcher jusqu’à atteindre le bout de la rue…\n",
        "\n",
        "Imaginons que nous voulions demander un mot de passe à l’utilisateur et\n",
        "vérifier s’il est correct dans une application (ne faites pas comme\n",
        "cela, c’est pour illustrer, ce n’est pas sécuritaire) :\n",
        "\n",
        "``` python\n",
        "# Le mot de passe attendu\n",
        "correct_password = \"python123\"\n",
        "\n",
        "# Demande à l'utilisateur de saisir le mot de passe\n",
        "entered_password = input(\"Veuillez entrer le mot de passe: \")\n",
        "\n",
        "# Continue à demander tant que le mot de passe saisi n'est pas correct (note si le mot de passe est le bon dès le début, on ne rentre pas dans la boucle)\n",
        "while entered_password != correct_password:\n",
        "    # Ce code sera exécuté dans que le mot de passe n'est pas le bon. Cela permet de bloquer la suite du programme tant que la condition n'est pas remplie.\n",
        "    entered_password = input(\"Mot de passe incorrect. Réessayez: \")\n",
        "\n",
        "# L'utilisateur a saisi le bon mot de passe\n",
        "print(\"Mot de passe accepté, accès autorisé.\")\n",
        "```\n",
        "\n",
        "Pour comprendre ce bout de code, nous devons le décomposer :\n",
        "\n",
        "-   `while entered_password != correct_password` :\n",
        "    -   `while` défini l’entrée dans la boucle\n",
        "    -   `entered_password != correct_password` représente la condition\n",
        "        d’arrêt, tant qu’elle est fausse, la boucle continue. La valeur\n",
        "        de `entered_password` est mise à jour dans le corps de la\n",
        "        boucle.\n",
        "    -   `index` défini le nom de la variable qui va contenir les\n",
        "        variables récupérées lors du parcours du range\n",
        "-   `entered_password = input(\"Mot de passe incorrect. Réessayez: \")` :\n",
        "    met à jour la valeur de `entered_password` en la demandant à\n",
        "    l’utilisateur\n",
        "\n",
        "### Différences entre les deux\n",
        "\n",
        "En python, les boucles `while` sont plus faciles à comprendre. En effet\n",
        "les boucles `for` utilisent des concepts plus avancés (dans d’autres\n",
        "langages on les appellerai `foreach` car elles manipulent des\n",
        "itérateurs). De plus, une boucle `while` peut toujours remplacer une\n",
        "boucle `for` (essayez de remplacer la boucle `for` de l’exemple\n",
        "précédent).\n",
        "\n",
        "Cependant, habituez vous à manipuler les boucles `for`, elles permettent\n",
        "d’exprimer plus facilement les concepts et surtout elles permettent\n",
        "d’éviter un problème gênant : **les boucles infinies**.\n",
        "\n",
        "Regardez le code suivant (si vous le lancez, il faudra faire `ctrl-c`\n",
        "pour arrêter le programme) :\n",
        "\n",
        "``` python\n",
        "valeur = 0\n",
        "while valeur < 1:\n",
        "    print(valeur)\n",
        "    # valeur = valeur + 0.1\n",
        "```\n",
        "\n",
        "La condition d’arrêt n’est jamais atteinte donc on ne sort jamais de la\n",
        "boucle et la boucle est infinie.\n",
        "\n",
        "**Note** : on obtient la même chose avec l’exemple sur le mot de passe,\n",
        "si on ne trouve pas le mot de passe, on ne sort pas de la boucle (dans\n",
        "ce cas là c’est le comportement attendu).\n",
        "\n",
        "**Note** : on peut aussi avoir des boucles infinies avec des `for`,\n",
        "c’est plus compliqué, il faut modifier l’élément que l’on parcours dans\n",
        "la boucle.\n",
        "\n",
        "## Boucles imbriquées\n",
        "\n",
        "Il est tout à fait possible d’imbriquer des boucles entre elles.\n",
        "\n",
        "Un exemple typique est l’affichage de tables de multiplications :"
      ],
      "id": "b27b7a42-a7bb-4981-94c2-65593a2c3dc4"
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "metadata": {},
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "   1    2    3    4    5    6    7    8    9   10 \n",
            "   2    4    6    8   10   12   14   16   18   20 \n",
            "   3    6    9   12   15   18   21   24   27   30 \n",
            "   4    8   12   16   20   24   28   32   36   40 \n",
            "   5   10   15   20   25   30   35   40   45   50 \n",
            "   6   12   18   24   30   36   42   48   54   60 \n",
            "   7   14   21   28   35   42   49   56   63   70 \n",
            "   8   16   24   32   40   48   56   64   72   80 \n",
            "   9   18   27   36   45   54   63   72   81   90 \n",
            "  10   20   30   40   50   60   70   80   90  100 "
          ]
        }
      ],
      "source": [
        "# Parcours des chiffres de 1 à 10 pour la table de multiplication\n",
        "for i in range(1, 11):\n",
        "    # Parcours des chiffres de 1 à 10 pour multiplier avec i\n",
        "    for j in range(1, 11):\n",
        "        # Calcul du produit et affichage avec un formatage pour l'alignement\n",
        "        print(f\"{i*j:4}\", end=' ')\n",
        "    # Retour à la ligne après chaque ligne de la table\n",
        "    print()"
      ],
      "id": "d96229ec-352a-4213-9bc0-762050689850"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "On remarque que l’intérieur de la boucle sur les `j` à accès aux valeurs\n",
        "de `i`.\n",
        "\n",
        "Les boucles imbriquées peuvent rapidement devenir complexes, et il est\n",
        "important de veiller à ce qu’elles restent lisibles et maintenables. Il\n",
        "est également essentiel de comprendre leur impact sur les performances,\n",
        "car chaque niveau d’imbrication ajoute un niveau de complexité à\n",
        "l’ensemble de la boucle.\n",
        "\n",
        "**Note** : En python, il est possible d’imbriquer tous les blocs\n",
        "(boucles, conditions, fonctions, …) entre eux.\n",
        "\n",
        "## Conclusion\n",
        "\n",
        "Vous venez de découvrir le concept des boucles en Python. Ces structures\n",
        "de contrôle fondamentales vous ouvrent les portes de l’écriture de\n",
        "programmes plus complexes.\n",
        "\n",
        "Pour rappel :\n",
        "\n",
        "-   les boucles `for` :\n",
        "    -   permettent d’exécuter un nombre connu à l’avance d’itérations\n",
        "    -   sont un peu complexes mais les plus utilisées en pratique\n",
        "-   les boucles `while` :\n",
        "    -   quand on ne connaît pas le nombre d’itération à l’avance mais un\n",
        "        critère d’arrêt\n",
        "    -   peuvent exprimer tout ce que les boucles `for` expriment\n",
        "    -   peuvent plus facilement causer des boucles infinies\n",
        "-   on peut imbriquer les boucles les unes dans les autres\n",
        "\n",
        "N’hésitez pas à prendre les exemples proposés et à les modifier pour\n",
        "bien comprendre le concept. C’est nouveau pour vous."
      ],
      "id": "fd5dd70c-505d-4f15-801a-865fbc5a9e1b"
    }
  ],
  "nbformat": 4,
  "nbformat_minor": 5,
  "metadata": {
    "kernelspec": {
      "name": "python3",
      "display_name": "blog-oh-ce-cours",
      "language": "python"
    },
    "language_info": {
      "name": "python",
      "codemirror_mode": {
        "name": "ipython",
        "version": "3"
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.12.0"
    }
  }
}