# Exercices de base - avec solutions

## But

* Se familiariser avec les bases de la gestion des exceptions avant de les appliquer à des énoncés plus complexes.

## Énoncé&#x20;

<mark style="color:red;">Pour chacun des exercices suivants, vous devez :</mark>

* **Tester différentes données/entrées** possibles pour vos fonctions de façon à **faire sortir les exceptions**. Exemples :
  * On entre des valeurs de différents types que ce qui est demandé.
  * On entre des valeurs spécifiques qui risquent de compromettre un calcul.
  * On entre autre chose qu'une liste pour une opération sur les listes.
  * On entre une liste vide.
  * etc.
* **Lisez le message d'erreur** attentivement pour le comprendre et vous familiariser avec.
* **Gérez les exceptions** ou **corrigez les erreurs** selon les bonnes pratiques.

## Exercice 1

Créez une fonction qui permet de calculer et retourner la division entre deux nombres entiers. Les deux nombres doivent êtres entrés par l'utilisateur dans votre programme principal.

Arrondissez maintenant le résultat de la division à l'aide de la fonction `round` . Voir la description de round [ici](https://docs.python.org/fr/3/library/functions.html#round).

{% hint style="info" %}
**Clin d'œil :** L'endroit où vous le faites peut vous éviter de devoir gérer une exception de plus. Cela dépend aussi de votre solution.
{% endhint %}

<details>

<summary><mark style="color:green;">Solution</mark></summary>

```python
def division(nombre1: int, nombre2: int) -> float:
    """
    Cete fonction fait la division entre les deux nombres
    passés en paramètres et retourne le résultat.
    :param nombre1: Le 1er nombre entier.
    :param nombre2: Le 2ème nombre entier.
    :return: Le résultat de division entre nombre1 et nombre2
    """
    try:
        resultat_division = round(nombre1 / nombre2)
        return resultat_division
        
    except ZeroDivisionError:
        return None
        
    except TypeError:
        print("Les deux nombres doivent être des entiers")
        return None

if __name__ == "__main__":

    try:
        nb1 = int(input("Veuillez entrer le 1er nombre entier : "))
        nb2 = int(input("Veuillez entrer le 2ème nombre entier : "))
        res_division = round(division(nb1, nb2))
        if res_division is None :
            print("Impossible de faire une division par zéro.")
        else:
            print(f"Le résultat de la division entre {nb1} et {nb2} est égal à {res_division}")
    
    except ValueError:
        print("Les deux nombres doivent être des entiers")

```

</details>

## Exercice 2

Créez une fonction qui permute (échange les positions de) deux éléments d'une liste. La liste et les deux indices doivent être donnés à cette fonction.

<details>

<summary><mark style="color:green;">Solution</mark></summary>

```python
def permutation_elements_liste(liste: list, i: int, j: int):
    """
    Cette fonction permet de permuter 2 éléments d'une
    liste étant donné leurs indices.
    :param liste: La liste sur laquelle on veut faire la permutation.
    :param i: L'indice de l'élément à permuter.
    :param j: L'indice de l'autre élément à permuter.
    :return: La liste avec les deux éléments permutés.
    """

    try:
        liste[i], liste[j] = liste[j], liste[i]
    except TypeError:
        print("""Aucune permutation effectuée. 
                 L'indice de la liste doit être un nombre entier ou 
                 le premier paramètre de la fonction n'est pas une liste.""")
        return None
    except IndexError:
        print("Aucune permutation effectuée. L'élément à l'indice que vous avez donné n'existe pas. Valeurs d'indices attendues de 0 à 5.")
        return None
    return liste

if __name__ == "__main__":
    liste = [1, 2, 3, 4, 5, 6]
    print(f"La liste d'origine est {liste}")

    indice1 = 4
    indice2 = 3

    print(f"Permutation des éléments aux indices {indice1} et {indice2} en cours...")

    liste_perm = permutation_elements_liste(liste, i=indice1, j=indice2)

    if liste_perm is not None:
        print(f"La liste avec les éléments permutés est {liste_perm}")
```

</details>

## Exercice 3

Soit l'exemple suivant :&#x20;

```python
def trier_liste(liste: list) -> None :
    liste.sorted()

if __name__ == "__main__":
    liste_nums = [6, 3, 5, 2, 4, 1]
    trier_liste(liste_nums)
    print(liste_nums)
```

* Exécutez-le et lisez l'erreur.
* Quel est le type d'exception? Qu'est-ce que cela signifie ?
* Que faut-il faire dans ce cas, gérer l'exception ou corriger l'erreur?

<details>

<summary><mark style="color:green;">Solution</mark></summary>

```python

# ******************* Réponses aux questions de l'exercice ******************* #
# Exécutez-le et lisez l'erreur.
#       AttributeError: 'list' object has no attribute 'sorted'. Did you mean: 'sort'?
# Quel est le type d'exception? Qu'est-ce que cela signifie ?
#       Type d'exception : AttributeError
#       Signification : Une liste n'a pas d'attribut (ici il s'agit d'une fonction native) appelé sorted().
#                      Fonction native proposée : sort().
# Que faut-il faire dans ce cas, gérer l'exception ou corriger l'erreur ?
#       Mettre liste.sort() à la place de liste.sorted()
# **************************************************************************** #

def trier_liste(liste: list) -> None :
    """
    Cette fonction trie la liste passée en paramètres.
    :param liste: liste à trier.
    :return: (Aucun).
    """
    # Correction 2 (en extra) : On gère l'exception où la valeur qu'on passe à cette fonction n'est pas une liste.
    try:
        # Correction 1 : sort() à la place de sorted()
        liste.sorted()
        print(liste_nums)
    except AttributeError:
        print(f"{liste_nums} ne peut pas être triée. La valeur passée à la fonction trier_liste doit être une liste.")

if __name__ == "__main__":
    liste_nums = [8, 7, 1, 5, 4]
    trier_liste(liste_nums)
```

</details>

## Exercice 4

```python
def multiplication(x, y):
    return COEFICIENT * x * y

if __name__ == "__main__":
    COEFFICIENT = 15
    resultat = multiplication(x = 8, y = 2)
    print(resultat)
```

* Exécutez-le et lisez l'erreur.
* Quel est le type d'exception? Qu'est-ce que cela signifie ?
* Que faut-il faire dans ce cas, gérer l'exception ou corriger l'erreur?

<details>

<summary><mark style="color:green;">Solution</mark></summary>

```python
# ******************* Réponses aux questions de l'exercice ******************* #
# Exécutez-le et lisez l'erreur.
#       NameError: name 'COEFICIENT' is not defined. Did you mean: 'COEFFICIENT'?
# Quel est le type d'exception? Qu'est-ce que cela signifie ?
#       Type d'exception : NameError
#       Signification : Le nom COEFICIENT n'est pas connu. Il y a une faute d'orthographe dans le nom de la constante.
# Que faut-il faire dans ce cas, gérer l'exception ou corriger l'erreur ?
#       Remplacer COEFICIENT par COEFFICIENT
# **************************************************************************** #

def multiplication(x: float, y: float) -> float:
    """
    Cette fonction multiplie deux nombres et retourne le résultat.
    :param x: premier nombre à multiplier.
    :param y: deuxième nombre à multiplier.
    :return: le résultat de la multiplication les deux nombres x et y passés en paramètres.
    """
    # Correction 2 (en extra) : On gère l'exception où la valeur qu'on passe à cette fonction est une liste.
    try:
        # Correction 1 : Correction du nom de la variable COEFFICIENT et non COEFICIENT
        return COEFFICIENT * x * y
    except TypeError:
        print(f"On ne peut pas multiplier {x} par {y}. Les valeurs passées à la fonction multiplication doivent être des nombres.")

if __name__ == "__main__":
    COEFFICIENT = 15
    resultat = multiplication(x = 8, y = 2)
    if resultat is not None:
        print(resultat)
```

</details>

## Exercice 5

Soit le programme suivant, exécutez le et expliquez l'erreur **sans la corriger** (<mark style="color:red;">vous devez utiliser le débogueur pour comprendre l'erreur</mark>).

```python
def calcul_moyenne_liste(liste:list[int]=[]) -> float:
    moyenne = sum(liste) / len(liste)
    return moyenne

if __name__ == "__main__":
    valeurs_liste_str = input("Veuillez entrer les valeurs d'une liste séparées par des virgules : ")
    liste_nombres = valeurs_liste_str.split(",")
    moyenne = calcul_moyenne_liste(liste_nombres)
    print(moyenne)
```

Voici la correction du programme précédent (<mark style="color:red;">vous n'avez pas besoin de comprendre la correction à la ligne 7 pour faire l'exercice</mark>) : &#x20;

{% code lineNumbers="true" %}

```python
def calcul_moyenne_liste(liste:list[int]=[]) -> float:
    moyenne = sum(liste) / len(liste)
    return moyenne

if __name__ == "__main__":
    valeurs_liste_str = input("Veuillez entrer les valeurs d'une liste séparées par des virgules : ")
    liste_nombres = [int(e) for e in valeurs_liste_str.split(",")]
    moyenne = calcul_moyenne_liste(liste_nombres)
    print(moyenne)
```

{% endcode %}

* Gérez les exceptions qui peuvent avoir lieu **dans votre fonction**.

<details>

<summary><mark style="color:green;">Solution</mark></summary>

```python
def calcul_moyenne_liste(liste:list[int]) -> float:
    """
    Cette fonction calcule la moyenne d'une liste d'entiers.
    :param liste: liste de nombres entiers.
    :return: la moyenne des éléments de la liste.
    """
    try:
        moyenne = sum(liste) / len(liste)
        
    except TypeError:
        print(f"Impossible de calculer la moyenne. La valeur donnée paramètre à la fonction calcul_moyenne_liste n'est pas une liste de nombres.")
        return None
        
    except ZeroDivisionError:
        print(f"Impossible de calculer la moyenne. Il doit y avoir au moins un élément dans la liste passée à la fonction.")
    
    else:
        return moyenne

if __name__ == "__main__":
    valeurs_liste_str = input("Veuillez entrer des nombres séparées par des virgules : ")

    try:
        liste_nombres = [int(e) for e in valeurs_liste_str.split(",")]
        
    except ValueError:
        print(f"Vous devez entrer des entiers séparés par des virgules et non des nombres rééls ou des caractères alphabétiques.")
    
    else:
        moyenne = calcul_moyenne_liste(liste_nombres)
        if moyenne is not None:
            print(moyenne)
```

</details>
