.. _td1acenoncesession2rst: ================================ 1A.1 - Variables, boucles, tests ================================ .. only:: html **Links:** :download:`notebook `, :downloadlink:`html `, :download:`python `, :downloadlink:`slides `, :githublink:`GitHub|_doc/notebooks/td1a/td1a_cenonce_session2.ipynb|*` Répétitions de code, exécuter une partie plutôt qu’une autre. .. code:: ipython3 from jyquickhelper import add_notebook_menu add_notebook_menu() .. contents:: :local: Partie 1 : variables, int, float, str, list ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Un algorithme manipule des données. Ces données ne sont pas connues au moment où on écrit l’algorithme. Les variables servent à nommer ces données afin de pouvoir écrire cet algorithme. On procède la plupart du temps dans l’ordre suivant : - On écrit l’algorithme. - On affecte des valeurs aux variables. - On exécute l’algorithme. Quelques exemples à essayer autour des variables : .. code:: ipython3 i = 3 # entier = type numérique (type int) r = 3.3 # réel = type numérique (type float) s = "exemple" # chaîne de caractères = type str (exemple n'est pas une variable) s = 'exemple' # " et ' peuvent être utilisées pour définir une chaîne de caractères sl = """ exemple sur plusieurs lignes""" # on peut définir une chaîne sur plusieurs lignes avec """ ou ''' n = None # None signifie que la variable existe mais qu'elle ne contient rien # elle est souvent utilisée pour signifier qu'il n'y a pas de résultat # car... une erreur s'est produite, il n'y a pas de résultat # (racine carrée de -1 par exemple) i,r,s,n, sl # avec les notebooks, le dernier print n'est pas nécessaire, il suffit d'écrire # i,r,s,n .. parsed-literal:: (3, 3.3, 'exemple', None, ' exemple sur\nplusieurs lignes') .. code:: ipython3 v = "anything" # affectation print ( v ) # affichage v1, v2 = 5, 6 # double affectation v1,v2 .. parsed-literal:: anything .. parsed-literal:: (5, 6) Par défaut, le notebook affiche le résultat présent sur la dernière ligne de la cellule. S’il on souhaite en afficher plusieurs, il faut utiliser la fonction `print `__. .. code:: ipython3 x = 3 print(x) y = 5 * x y .. parsed-literal:: 3 .. parsed-literal:: 15 .. code:: ipython3 x,y = 4,5 s = "addition" "{3} de {0} et {1} donne : {0} + {1} = {2}".format (x,y,x+y,s) .. parsed-literal:: 'addition de 4 et 5 donne : 4 + 5 = 9' La dernière écriture permet d’assembler différentes valeurs en une seule chaînes de caractères. C’est très pratique lorsqu’on veut répéter le même assemblage un grand nombre de fois. Ce mécanisme ressemble à celui des lettres type : c’est un texte à trou qu’on remplit avec des valeurs différentes à chaque fois. .. code:: ipython3 for prenom in [ "xavier", "sloane"] : print ("Monsieur {0}, vous avez gagné...".format(prenom)) .. parsed-literal:: Monsieur xavier, vous avez gagné... Monsieur sloane, vous avez gagné... **Type d’une variable :** .. code:: ipython3 print ( type ( v ) ) # affiche le type d'une variable print ( isinstance (v, str) ) # pour déterminer si v est de type str .. parsed-literal:: True **Les tableaux ou listes (list) :** .. code:: ipython3 c = (4,5) # couple de valeurs (ou tuple) l = [ 4, 5, 6.5] # listes de valeurs ou tableaux x = l [0] # obtention du premier élément de la liste l y = c [1] # obtention du second élément le = [ ] # un tableau vide c,l,x,y,le .. parsed-literal:: ((4, 5), [4, 5, 6.5], 4, 5, []) .. code:: ipython3 l = [ 4, 5 ] l += [ 6 ] # ajouter un élément l.append ( 7 ) # ajouter un élément l.insert (1, 8) # insérer un élément en seconde position print(l) del l [0] # supprimer un élément del l [0:2] # supprimer les deux premiers éléments l .. parsed-literal:: [4, 8, 5, 6, 7] .. parsed-literal:: [6, 7] **Longueur d’une liste et autres :** .. code:: ipython3 l = [ 4, 5, 6 ] print ( len(l) ) # affiche la longueur du tableau print ( max(l) ) # affiche le plus grand élément s = l * 3 # création de la liste [ 4, 5, 6, 4, 5, 6, 4, 5, 6 ] t = s [ 4:7 ] # extraction de la sous-liste de la position 4 à 7 exclu s [4:7] = [ 4 ] # remplacement de cette liste par [ 4 ] s .. parsed-literal:: 3 6 .. parsed-literal:: [4, 5, 6, 4, 4, 5, 6] Type **mutable** et **immutable** (voir aussi `Qu’est-ce qu’un type immuable ou immutable ? `__) : une liste est un type **mutable**. Cela veut dire que par défaut, l’instruction ``list1=list2`` ne recopie pas la liste, elle lui donne un autre nom qui peut être utilisé en même temps que le premier. .. code:: ipython3 l1 = [ 0, 1 ,2 ] l2 = l1 l2[0] = -1 l1,l2 .. parsed-literal:: ([-1, 1, 2], [-1, 1, 2]) Les deux listes sont en apparence modifiées. En fait, il n’y en a qu’une. Pour créer une copie, il faut explicitement demander une copie. .. code:: ipython3 l1 = [ 0, 1 ,2 ] l2 = list(l1) l2[0] = -1 l1,l2 .. parsed-literal:: ([0, 1, 2], [-1, 1, 2]) C’est un point très important du langage qu’il ne faut pas oublier. On retrouve cette convention dans la plupart des `langages interprétés `__ car faire une copie alourdit le temps d’exécution. Partie 2 : Tests ~~~~~~~~~~~~~~~~ Les tests permettent de faire un choix : selon la valeur d’une condition, on fait soit une séquence d’instructions soit une autre. .. code:: ipython3 v = 2 if v == 2 : print ("v est égal à 2") else : print ("v n'est pas égal à 2") .. parsed-literal:: v est égal à 2 La clause ``else`` n’est obligatoire : .. code:: ipython3 v = 2 if v == 2 : print ("v est égal à 2") .. parsed-literal:: v est égal à 2 Plusieurs tests enchaînés : .. code:: ipython3 v = 2 if v == 2 : print ("v est égal à 2") elif v > 2 : print ("v est supérieur à 2") else : print ("v est inférieur à 2") .. parsed-literal:: v est égal à 2 Partie 3 : boucles ~~~~~~~~~~~~~~~~~~ Les boucles permettent de répéter un nombre fini ou infini de fois la même séquence d’instructions. Quelques exemples à essayer autour des boucles : .. code:: ipython3 for i in range (0, 10) : # on répète 10 fois print ("dedans",i) # l'affichage de i # ici, on est dans la boucle # ici, on n'est plus dans la boucle "dehors",i # on ne passe par 10 .. parsed-literal:: dedans 0 dedans 1 dedans 2 dedans 3 dedans 4 dedans 5 dedans 6 dedans 7 dedans 8 dedans 9 .. parsed-literal:: ('dehors', 9) **Boucle while :** .. code:: ipython3 i = 0 while i < 10 : print (i) i += 1 .. parsed-literal:: 0 1 2 3 4 5 6 7 8 9 **Interrompre une boucle :** .. code:: ipython3 for i in range (0, 10) : if i == 2 : continue # on passe directement au suivant print (i) if i > 5 : break # interruption définitive .. parsed-literal:: 0 1 3 4 5 6 **Parcours d’une liste :** observer les différences entre les trois écritures .. code:: ipython3 l = [ 5, 3, 5, 7 ] for i in range (0, len(l)) : print ("élément ",i, "=", l [ i ] ) .. parsed-literal:: élément 0 = 5 élément 1 = 3 élément 2 = 5 élément 3 = 7 .. code:: ipython3 l = [ 5, 3, 5, 7 ] for v in l : print ("élément ", v ) .. parsed-literal:: élément 5 élément 3 élément 5 élément 7 .. code:: ipython3 l = [ 5, 3, 5, 7 ] for i,v in enumerate(l) : print ("élément ",i, "=", v ) .. parsed-literal:: élément 0 = 5 élément 1 = 3 élément 2 = 5 élément 3 = 7 **Que fait le programme suivant ?** .. code:: ipython3 l = [ 4, 3, 0, 2, 1 ] i = 0 while l[i] != 0 : i = l[i] print (i) # que vaut l[i] à la fin ? .. parsed-literal:: 4 1 3 2 On peut jouer avec des cartes pour faire dénouer le côté sybillin de ce programme : `La programmation avec les cartes `__. Partie 4 : les listes compactes, les ensembles ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Plutôt que d’écrire : .. code:: ipython3 l = [ ] for i in range (10) : l.append( i*2+1) l .. parsed-literal:: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] On peut écrire : .. code:: ipython3 l = [ i*2+1 for i in range(10) ] l .. parsed-literal:: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] Quelques examples à essayer : .. code:: ipython3 l = [ i*2 for i in range(0,10) ] l # qu'affiche l ? .. parsed-literal:: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] .. code:: ipython3 l = [ i*2 for i in range(0,10) if i%2==0 ] l # qu'affiche l ? .. parsed-literal:: [0, 4, 8, 12, 16] Les ensembles ou **set** sont des listes pour lesqueelles les éléments sont uniques. Si deux nombres nombres *int* et *float* sont égaux, seul le premier sera conservé. .. code:: ipython3 l = [ "a","b","c", "a", 9,4,5,6,7,4,5,9.0] s = set(l) s .. parsed-literal:: {4, 5, 6, 7, 'a', 9, 'c', 'b'} Partie 5 : recherche non dichotomique (exercice) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ On veut écrire quelques instructions pour trouver la position du nombre ``x = 7`` dans la liste ``l``. Il faut compléter le programme suivant en utilisant une boucle et un test. .. code:: ipython3 l = [ 3, 6, 2 , 7, 9 ] x = 7 # ...... print ( position ) Partie 6 : Recherche dichotomique ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ La `recherche dichotomique `__ consiste à chercher un élément ``e`` dans un tableau trié ``l``. On cherche sa position : - On commence par comparer ``e`` à l’élément placé au milieu du tableau d’indice ``m``, s’ils sont égaux, on a trouvé, - s’il est inférieur, on sait qu’il se trouve entre les indices 0 et ``m-1``, - s’il est supérieur, on sait qu’il se trouve entre les indices ``m+1`` et la fin du tableau. Avec une comparaison, on a déjà éliminé une moitié de tableau dans laquelle on sait que ``p`` ne se trouve pas. On applique le même raisonnement à l’autre moitié pour réduire la partie du tableau dans laquelle on doit chercher. .. code:: ipython3 l = sorted( [ 4, 7, -1,3, 9, 5, -5 ] ) # recherche dichotomique # la position retournée est correspond à celle de l'élément dans le tableau trié Partie 7 : pour aller plus loin ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Que fait la fonction écrite à la question précédente lorsque l’élément ne se trouve pas dans le tableau ? - Comparer le coût d’une recherche classique et celui d’une recherche dichotomique. On appelle coût d’un algorithme le nombre d’opérations qu’il faut pour atteindre le résultats. Dans ce cas, ce coût correspond au nombre d’itérations, c’est-à-dire le nombre de passage dans la boucle. Comme ce coût dépend des données en entrée, on experime généralement ce coût en fonction de la taille des données.