# Structures logiques répétitives (boucles)

## Introduction

La structure répétitive (ou boucle) est une répétition du même bloc de code, jusqu’à l’obtention d’un résultat escompté. L'arrêt de cette boucle se fait selon une condition ou après un certain nombre d'itérations déterminé.

Il existe deux types de boucles en Python : les boucles ***`while`*** et les boucles ***`for`***.

## Boucles while

Le traitement s’exécute tant que la condition à l’entrée de la structure est vraie, donc le code est exécuté de 0 à plusieurs fois. La structure se lit : "`tant que` la *`condition` est vraie,* `exécuter les`*`instructions`"*.

#### &#x20;Syntaxe Python

```python
while <condition>:
  <instructions à répéter>
```

#### Exemple 1

```python
compteur = 1
while compteur < 10:
  print("compteur = ", compteur)
  compteur += 1
```

{% hint style="info" %}
Notez que pour un arrêt assuré de la boucle, la condition doit évoluer, i.e. elle doit passer de `True` à `False` à un moment donné. Dans l'exemple précédent, on incrémente le `compteur` à chaque itération, ce qui fait que lorsque le compteur est égal à 10, on sort immédiatement de la boucle.
{% endhint %}

## Boucle for

Le traitement se répète autant de fois qu'il y a d'éléments dans une collection (un ensemble d'éléments, exemple : une liste). La structure se lit : `pour chaque élément` dans la *`collection`* `exécuter les`` `*`instructions`*.

#### &#x20;Syntaxe Python

```python
for <c> in <collection>:
  <instructions à répéter>
```

## La fonction `range()`

La fonction native `range()` est utilisé lorsqu'on veut itérer à travers une séquence de nombres. Elle est souvent utilisée dans les boucles for.

{% hint style="info" %}
Notez que la fonction `range()` ne génère pas une liste d'entiers, mais plutôt un objet de type "range". Vous pouvez le convertir en liste en utilisant `list().`
{% endhint %}

* `range(stop)` : génère une séquence de nombres de `0` jusqu'à `stop-1`. Exemple :&#x20;

<figure><img src="https://700524925-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fn5YnWU89G98lz0ROIcGu%2Fuploads%2FKf4QGSnPgKscLFsFs0y2%2Fimage.png?alt=media&#x26;token=4b2cc4a0-1914-4da8-afde-2f3a52445076" alt="" width="206"><figcaption></figcaption></figure>

{% code title="Essayez ceci :" %}

```python
for i in range(10):
    print(i)
```

{% endcode %}

* `range(start, stop)` : génère une séquence de nombres de `start` jusqu'à `stop-1`. Exemple :&#x20;

<figure><img src="https://700524925-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fn5YnWU89G98lz0ROIcGu%2Fuploads%2FyWbe0O9f9p6k2rkfGFDd%2Fimage.png?alt=media&#x26;token=847b39c8-17bd-4d61-810b-f98bb6fb4cf2" alt="" width="155"><figcaption></figcaption></figure>

{% code title="Essayez ceci :" %}

```python
for i in range(4, 10):
    print(i)
```

{% endcode %}

* `range(start, stop, step)` : génère une séquence de nombres de `start` jusqu'à `stop-1` par pas de `step`. Exemple :&#x20;

<figure><img src="https://700524925-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fn5YnWU89G98lz0ROIcGu%2Fuploads%2FF9cQuEKZyqMuglyNZo9Y%2Fimage.png?alt=media&#x26;token=233865a3-07f7-43a9-9cda-ec898e617c8a" alt="" width="178"><figcaption></figcaption></figure>

{% code title="Essayez ceci :" %}

```python
for i in range(4, 10, 2):
    print(i)
```

{% endcode %}

## Les instructions de contrôle des boucles

### `break`

Permet de sortir prématurément de la boucle for ou while la plus proche (dans le cas de plusieurs boucles imbriquées).

#### Exemple

Dans cet exemple, l'exécution de la boucle s'arrête lorsque i est égal à 7. Les valeurs affichées sont 0, 1, 2, 3, 4, 5 et 6.

```python
for i in range(10):
    if i == 7:
        break
    print(i)
```

### `continue`

Permet de passer immédiatement à l'itération suivante d'une boucle for ou while sans exécuter le reste du code.

#### Exemple

Dans cet exemple, lorsque i est égal à 3, on passe à l'itération suivante (i=4) sans exécuter le `print(i)`. Les valeurs de 0 à 9 sont toutes affichées sauf 3.

```python
for i in range(10):
    if i == 3:
        continue  # Passe à l'itération suivante sans exécuter les instructions suivantes
    print(i)
```

### `else`

Une clause `else` peut être incluse après une boucle `for` ou `while`. Le bloc else contient des instructions qui seront exécutées une fois que la boucle est terminée.

* Dans une boucle `for`, le bloc `else` est exécuté après que la boucle ait atteint sa dernière itération.
* Dans une boucle `while`, le bloc `else` est exécuté après que la condition de la boucle ait atteint la valeur `False`.

Dans les deux cas, le bloc `else` n'est pas exécuté lorsque la boucle a été arrêté via un `break`.

#### Exemple 1

Dans cet exemple, la boucle s'exécute jusqu'à la fin (i==9), donc le bloc `else` est exécuté et affiche le message "La boucle est terminée.".

```python
for i in range(10):
    print(i)
else:
    print("La boucle est terminée.")
```

#### Exemple 2

Dans cet exemple, la boucle est interrompue à l'itération 7, donc le bloc `else` ne s'exécute pas.

```python
for i in range(10):
    if i == 7:
        break  # Sort de la boucle
    print(i)
else:
    print("La boucle est terminée.")
```

## Exemple boucles imbriquées

* Il est possible d'avoir deux boucles (ou plus) imbriquées l'une à l'intérieur de l'autre.
* `continue` et `break` s'appliquent à la boucle la plus proche d'eux. i.e.&#x20;

Dans l'exemple suivant, si `break` s'exécute, on sort de la boucle intérieure (la plus proche), mais on continue l'exécution de la boucle extérieure normalement car `break` ne s'applique pas sur celle-ci.

```python
for i in range(1, 4):
    print(f"Boucle extérieure, itération {i}")

    for j in range(1, 6):
        if j == 3:
            continue

        if i == 2 and j == 4:
            break
        print(f"   Boucle intérieure, itération {j}")
        
    print("-----------------------------------")
```

## Exemple de boucle while True/break

Parfois, nous devons forcer la création de boucles infinies et utiliser le mot clé *`break`* pour en sortir sous une condition. Cette pratique doit cependant être limitée à des cas où un `while <condition>` ne s'applique pas.&#x20;

#### Exemple

{% hint style="danger" %}
À la place de cette boucle :&#x20;

```python
while True:
    commande = input("Entrer une commande: ")
    if commande == "exit":
        break
```

{% endhint %}

{% hint style="success" %}
Privilégiez cette boucle :&#x20;

```python
commande = ""
while commande != "exit":
    commande = input("Entrer une commande: ")
```

{% endhint %}

***

## Exemples avec des listes

#### Exemple 1 : parcours d'une liste avec la boucle while

```python
fruits = ['pommes', 'poires', 'bleuets', 'raisins', 'bananes', 'pamplemousse']

i = 0
while i < len(fruits):
    print("fruit = ", fruits[i])
    i += 1
```

#### Exemple 2 : parcours d'une liste par éléments avec la boucle for

```python
fruits = ['pommes', 'poires', 'bleuets', 'raisins', 'bananes', 'pamplemousse']

for fruit in fruits:
  print("fruit = ", fruit)
```

#### Exemple 3 : parcours d'une liste par les indices avec la boucle for

([Voir la description de la fonction range()](#la-fonction-range))

```python
fruits = ['pommes', 'poires', 'bleuets', 'raisins', 'bananes', 'pamplemousse']

for i in range(len(fruits)):
  print("fruit = ", fruits[i])
```

{% hint style="info" %}
Notez que contrairement aux boucles *while*, les valeurs de i évoluent en prenant le prochain élément de la liste (retournée par `range(len(fruits))`) à chaque fois, nous n'avons pas besoin de le faire nous même.&#x20;
{% endhint %}

## Référence

{% embed url="<https://docs.python.org/3/tutorial/controlflow.html#for-statements>" %}
