Skip to content

NSI - Première - Projet : algorithmes de parcours séquentiel d’un tableau

Algorithmes de parcours séquentiel d’un tableau

Cliquez sur le lien du chapitre de cours à consulter:

Les exceptions

Une exception est une interruption de l’exécution du programme qui peut être prévue par le développeur ou décidée par l’interpréteur python notamment quand une donnée n’est pas conforme au code qui la manipule et dans beaucoup d’autres situations.

Lorqu’une exception est levée, un message d’erreur s’affiche dans la console avec le type d’exception. Les exceptions courantes sont:

  • NameError : Accès à une variable qui n’existe pas.
  • IndexError : Accès à un indice de tableau qui n’existe pas
  • TypeError : opération appliquée à des valeurs incompatibles.

Il est possible de déclencher une exception avec le mot clé raise

 def  indice_du_minimum_tableau(t):
  # EXCEPTION LEVEE SI tableau t vide
  if  len(t) == 0 :
    raise ValueError('cette fonction n’accepte pas les tableaux vides') 
On peut aussi gérer des exceptions particulières dans un bloc try et except, on place dans le bloc try le code à risque; en cas de levée d’un exception par l'interpréteur, l’exécution du code placé dans try est interrompue par ce dernier et le bloc de code placé dans except est exécuté à la place, exemple:

try :
  # ici un code à risque: on demande un nombre à l'utilisateur du logiciel  
  nombre = int(input( "entrez votre nombre de notes:"))
  if  nombre <= 0 :
    # si l'utilisateur saisit un nombre nul ou négatif, on lève une exception:
    raise ValueError('veuillez entrer un nombre entier naturel supérieur à 0')
except:
  '''si l'utilisateur n'a pas saisi des caractères qui peuvent se convertir 
  en nombre, une exception est levée lorsque la fonction int
  essaie de convertir la donnée transmise par input, 
  le bloc de code du try est interrompu et le bloc de code du  
  except s'exécute:'''

  print("la donnée saisie n’est pas valide")

Pré-conditions - Post-conditions

L’instruction assert , combine un test de condition et déclenche une exception de type AssertionError avec un affichage personnalisé, exemple :

assert len(t) > 0, "le tableau ne doit pas être vide"
Lors de l’exécution avec un tableau t vide, le code affichera:

On distinguera deux types d'utilisation d'assert:

Les pré-conditions

On peut utiliser assert comme précondition à l’exécution d’un bloc de code. Si l’assertion s’avère fausse le code s’interrompt et une exception de type AssertionError est levée.

Exemple de code:

def indice_du_minimum_tableau(t: List[int]) -> int:
  """ Cette fonction renvoie l’indice du plus petit des nombres 
  d’un tableau non vide d’entiers  """
  indice_minimum = 0
  # avant l'exécution de la boucle, on vérifie que le tableau n'est pas vide
  assert len(t) > 0, "le tableau ne doit pas être vide"    
  for i in range(len(t)):
      if t[i] < t[indice_minimum]:
          indice_minimum = i
  return indice_minimum

L’instruction assert peut être combinée avec la fonction isinstance(une_donnée, un_type) pour vérifier que la donnée une_donnée est du type un_type. La fonction isinstance(..) renvoie True si le premier argument (une_donnée) est du type donné en second argument (un_type), exemples:

isinstance( 5, int ) : renvoie True parce que 5 est bien un objet de type int

isinstance( 5.0, int ) : renvoie False parce que 5.0 est un objet de type float

Exemple de code:

def indice_du_minimum_tableau(t: List[int]) -> int:
  """ Cette fonction renvoie l’indice du plus petit des nombres 
  d’un tableau non vide d’entiers  """
  indice_minimum = 0
  # avant l'exécution de la boucle, on vérifie que le tableau n'est pas vide:
  assert len(t) > 0, "le tableau ne doit pas être vide"    
  for i in range(len(t)):
      # avant de comparer l'élément du tableau, on vérifie son type:
      assert isinstance( t[i],  int ) , " le tableau ne doit contenir que des nombres entiers"
      if t[i] < t[indice_minimum]:
          indice_minimum = i
  return indice_minimum

Les post-conditions

On peut utiliser des assertions comme post-conditions, dans ce cas l’assertion permet de vérifier la correction du code (si le programme donne bien les résultats attendus).

Exemple de code:

Par exemple pour la fonction indice_du_minimum_tableau, si l'argument est:

[ 1, 2, 3, -4, 5] alors elle doit renvoyer l’indice 3

[ 1, 2, 3, 4, 5] elle doit renvoyer l’indice 0

On codera ces deux tests ainsi:

def indice_du_minimum_tableau(t: List[int]) -> int:
  """ Cette fonction renvoie l’indice du plus petit des nombres 
  d’un tableau non vide d’entiers  """
  indice_minimum = 0
  # avant l'exécution de la boucle, on vérifie que le tableau n'est pas vide:
  assert len(t) > 0, "le tableau ne doit pas être vide"    
  for i in range(len(t)):
      # avant de comparer l'élément du tableau, on vérifie son type:
      assert isinstance( t[i],  int ) , " le tableau ne doit contenir que des nombres entiers"
      if t[i] < t[indice_minimum]:
          indice_minimum = i
  return indice_minimum

  # les deux post-conditions
  assert indice_du_minimum_tableau([ 1, 2, 3, -4, 5]) == 3
  assert indice_du_minimum_tableau([ 1, 2, 3, 4, 5]) == 0
Comment définir un bon ensemble de test ?

Il est difficile d’être exhaustif (prévoir tous les cas possibles).

Voici quelques points qu’il convient de vérifier.

  • Si le programme traite plusieurs cas, chacun des cas doit être testé.
  • Si une fonction renvoie une valeur booléenne ( True, False), il faut tester que les deux valeurs soient bien obtenues.
  • Si le programme manipule un tableau il faut tester pour un tableau vide.
  • Si le programme manipule un nombre entier, il faut tester pour une valeur négative et nulle.
  • Si le programme manipule un intervalle, il faut tester les valeurs limites de cet intervalle. Cas très fréquent dans les boucles range(min, max).

Programmation défensive

Les assertions décrites précédemment servent en phase de tests. Un code qui doit être en "production" doit intégrer une programmation défensive, c'est à dire anticiper les situations non conformes et donner un résultat en adéquation avec les données manipulées. Dans le cas d'une fonction qui doit renvoyer l'indice du plus petit nombre d'une liste, l'objet None peut être renvoyé pour signifier que le code ne peut pas donner de résultat cohérent quand la liste est vide ou si les données sont de types différents et donc incomparables par exemple.

On peut utiliser des tests et la fonction isinstance() mais pas d'assertions.

def indice_du_minimum_tableau(t: List[int]) -> int:
  """ Cette fonction renvoie l’indice du plus petit des nombres 
  d’un tableau non vide d’entiers  """
  # avant l'exécution de la boucle, on vérifie que le tableau n'est pas vide:
  if len(t) == 0:
      return None
  indice_minimum = 0    
  for i in range(len(t)):
      # on teste la nature de la donnée avant le test:
      if isinstance(t[i],int ): 
        if t[i] < t[indice_minimum]:
            indice_minimum = i
      # si if est False, on renvoie None
      else:
        return None 
  # à la fin de la boucle, on renvoie l'indice
  return indice_minimum