C7.2 : Assertions

Travail préliminaire (sur papier)

■ Préconditions et postconditions

Question : Rappeler ce que sont les préconditions et les postconditions d'une fonction.

Afficher la correction

Précondition

On appelle précondition, les conditions que l'état d'un programme doit vérifier pour que la suite fonctionne correctement.

Exemple : les types des paramètres d'une fonction sont des préconditions pour l'exécution de cette fonction.

Postcondition

On appelle postcondition, les conditions que l'état d'un programme respecte à un point donné de son exécution.

Exemple : le type d'une valeur renvoyée par une fonction est une postcondition de cette fonction.

■ Application

On considère le code suivant :

def f(t):
    a = 0
    for i in range(len(t)):
        if t[i] > t[a]:
            a = i
    return a

1) Que vaut f([0, 9, 4]) ?

2) Améliorer la lisibilité du code de cette fonction en choisissant des noms parlants, en ajoutant des annotations de type et une docstring complète pour la fonction.

3) Que renvoie la fonction :

Préciser les préconditions pour la fonction.

Afficher la correction

1)

>>>f([0, 9, 4])
1

2)

def indice_valmax(liste:list)->int:
    '''
    Renvoie l'indice du plus grand élément d'un liste
    Parameters:
        t : (list) Liste d'éléments comparables, la liste ne doit pas être vide
    Returns:
        () Plus grand élément de la liste
    '''
    i_max = 0
    for i in range(len(liste)):
        if liste[i] > liste[i_max]:
            i_max = i
    return i_max

3)

>>>f([-9, -4, -1])
2
>>>f([5, 0])
0
>>>f([])
0

Le dernier exemple montre que la fonction ne donne pas un résultats satisfaisant si la liste passée en paramètre et vide.

Les assertions en python

■ Définition

En informatique, une assertion est une condition qui doit être vraie pour que l'exécution du programme se poursuive. Dans le cas contraire, le programme est arrêté.

Les assertions sont en général utilisées dans les fonctions pour s'assurer que les préconditions sont bien respectées.

■ Les assertions en python

En Python, on utilise l’instruction assert

assert condition, 'Texte (facultatif) affiché lorsque le programme est interrompu si la condition n\'est pas respectée'

Si la condition n'est pas respectée, le programme est interrompu avec une erreur de type AssertionError et le texte est envoyé pour affichage dans la ligne de commande.

Exemple :

b = 5
assert b == 8, "La variable b n'est pas égale à 8"
print("Le programme se poursuit")

Dans cet exemple, la ligne 3 n'est pas exécutée. En effet le programme est interrompu à la ligne 2 car l'affirmation b == 8 n'est pas vérifiée.

■ Rappel sur la fonction isinstance

L'instruction isinstance(var, type) permet de tester le type d'une variable.
Exemple :

>>>isinstance(8, int)
True

Applications

Application III_app1

Reprendre le code de la fonction du I) en y ajoutant une assertion pour assurer que la liste passée en paramètre n'est pas vide.

Application III_app2

1) Proposer quelques lignes de code avec une assertion permettant d'assurer qu'une liste contient uniquement des entiers.

2) Compléter le code précédant pour assurer qu'une liste contient uniquement des entiers positifs ou nuls.

Application III_app3

On considère la fonction dont le début du code est donné ci-dessous :

from random import randint
def liste_uniques(N, d, f):
    """
    Renvoie une liste de N nombres entiers aléatoires entre d et f (compris) sans aucun doublon.
    """

1) Lister toutes les préconditions sur les paramètres de cette fonction.

2) Compléter le code de la fonction.

3) Ajouter des assertions au code de la fonction afin que le programme soit interrompu si les préconditions ne sont pas respectées.

Afficher la correction
from random import randint, shuffle
def liste_uniques_v1(N:int, d:int, f:int) ->list:
    """
    Renvoie une liste de N nombres entiers aléatoires entre d et f (compris) sans aucun doublon.
    """
    assert isinstance(N, int), "Le premier paramètre doit être entier"
    assert N >= 0, "Le premier paramètre doit être >= à 0"
    assert isinstance(d, int), "Le deuxième paramètre doit être entier"
    assert isinstance(f, int), "Le troisième paramètre doit être entier"
    assert f - d >= N - 1, "Il faut un écart suffisant entre le deuxième et le troisième paramètre"
    liste = []
    while len(liste) < N:
        nb = randint(d, f)
        if nb not in liste:
            liste.append(nb)
    return liste

def liste_uniques_v2(N:int, d:int, f:int) ->list:
    liste_complete = [nb for nb in range(d, f+1)]
    liste_finale = []
    for i in range(N):
        pos = randint(0, f - d - i)
        nb = liste_complete.pop(pos)
        liste_finale.append(nb)
    return liste_finale

def liste_uniques_v3(N:int, d:int, f:int) ->list:
    liste = [nb for nb in range(d, f + 1)]
    shuffle(liste)
    return liste[0:N]

# Programme principal
li = liste_uniques_v1(5, 10, 20)
print(li)