python index num

Identification

Infoforall

13 - Introduction aux index numériques


Nous allons voir aujourd'hui un nouveau type de stockage : les variables ayant un contenu accessible via un index numéroté.

Il s'agit de variables qui font référence à d'autres contenus et qu'on peut alors lire un élément à la fois.

Logiciel nécessaire pour l'activité : Thonny ou juste Python 3

Evaluation ✎ : questions 05-10-11-12-17

Résumé : Version HTML ou fond blanc ou ou PDF (couleur ou gris)

1 - Strings

Commençons par le premier type possédant un index que vous ayez rencontré : le string.

1 - Déclaration d'un string

Les éléments délimitateurs sont les guillemets.

On peut utiliser les guillemets simples ou doubles mais Python utilise les simples lors des affichages de "contenu".

Exemple

>>> a = "5" >>> a*2 '55' >>> type(a) <class 'str'> >>> type(a*2) <class 'str'>
2 - Nombre d'éléments stockés

On peut utiliser la fonction native len pour obtenir le nombre d'éléments (ici des caractères) stockés dans l'itérable.

Exemple

>>> a = "bonjour" >>> nbr = len(a) >>> nbr 7 >>> a = "bonjour !" >>> nbr = len(a) >>> nbr 9

On notera que l'espace est bien un caractère : il peut s'agir de l'espace, le code ASCII 32 qui contient donc " ".

01° Trouver (à l'aide d'un code Python) le nombre de caractères (caractères d'espacement et de ponctuation inclus) de chacune des phrases suivantes :

Phrase 1

On notera que l'index du premier élément ne porte pas le numéro 1 mais bien le numéro 0 !

Phrase 2

On notera également qu'on peut avoir accès à l'élément 5 sans avoir lu au préalable le 2,3 et 4. Ce n'est pas le cas pour toutes les structures de données.

...CORRECTION...

1 2 3 4 5
phrase1 = "On notera que l'index du premier élément ne porte pas le numéro 1 mais bien le numéro 0 !" phrase2 = "On notera également qu'on peut avoir accès à l'élément 5 sans avoir lu au préalable le 2,3 et 4. Ce n'est pas le cas pour toutes les structures de données." print(len(phrase1)) print(len(phrase2))

On obtient alors les réponses suivantes : 89 et 155.

3 - Accès à l'un des éléments

Pour accéder à l'un des caractères en particuliers, on peut noter le nom de la variable suivi de crochets et y placer l'index du numéro voulu.

Exemple

>>> a = "bonjour" >>> lettre = a[0] >>> lettre 'b' >>> lettre = a[1] >>> lettre 'o' >>> lettre = a[5] >>> lettre 'u'

La correspondance index - caractère donne ceci sur l'exemple

Index 0 1 2 3 4 5 6
'bonjour' 'b' 'o' 'n' 'j' 'o' 'u' 'r'

On notera que l'index du premier élément porte le numéro d'index 0 et pas le numéro 1  !.

On notera également qu'on peut avoir accès à l'élément 5 sans avoir lu au préalable le 2,3 et 4. Ce n'est pas le cas pour toutes les structures de données.

02° Trouver le 27e caractére de chacune des phrases suivantes :

Phrase 1

On notera que l'index du premier élément ne porte pas le numéro 1 mais bien le numéro 0 !

Phrase 2

On notera également qu'on peut avoir accès à l'élément 5 sans avoir lu au préalable le 2,3 et 4. Ce n'est pas le cas pour toutes les structures de données.

...CORRECTION...

1 2 3 4 5
phrase1 = "On notera que l'index du premier élément ne porte pas le numéro 1 mais bien le numéro 0 !" phrase2 = "On notera également qu'on peut avoir accès à l'élément 5 sans avoir lu au préalable le 2,3 et 4. Ce n'est pas le cas pour toutes les structures de données." print(phrase1[26]) print(phrase2[26])
4 - Lecture des éléments un à un par index (méthode classique par boucle numérique)

On peut aussi lire les éléments un par un en utilisant une boucle FOR couplée à la fonction len pour connaitre la valeur limite à placer pour l'indice d'incrémentation de la boucle.

Ainsi avec "bonjour", on a 7 lettres avec un index 0-1-2-3-4-5-6.

Il faudrait donc utiliser for index in range(7) :

Exemple

1 2 3 4 5
a = 'bonjour' longueur = len(a) for index in range(longueur) : print(a[index])

Ce programme va afficher ceci dans la console :

b o n j o u r

Si on désire les voir s'afficher en les séparant par un tiret, on peut utiliser ceci :

1 2 3 4 5
a = 'bonjour' longueur = len(a) for index in range(longueur) : print(a[index], end="-")

On obtient alors ceci

b-o-n-j-o-u-r-

03° Réaliser un court programme qui affiche caractère par caractère l'une de deux phrases précédentes (avec passage à la ligne entre chaque caractère).

Ensuite, s'arranger pour compter les "e" en utilisant un compteur nbr_e. Il faudra l'initialiser avant de rentrer dans la boucle.

Phrase 1

On notera que l'index du premier élément ne porte pas le numéro 1 mais bien le numéro 0 !

Phrase 2

On notera également qu'on peut avoir accès à l'élément 5 sans avoir lu au préalable le 2,3 et 4. Ce n'est pas le cas pour toutes les structures de données.

Vous devriez découvrir 11 et 16 'e' dans les phrases 1 et 2.

...CORRECTION...

1 2 3 4 5 6 7 8 9 10 11
phrase1 = "On notera que l'index du premier élément ne porte pas le numéro 1 mais bien le numéro 0 !" longueur = len(phrase1) nbr_e = 0 for index in range(longueur) : caractere = phrase1[index] print(caractere) if caractere == 'e' : nbr_e = nbr_e + 1 print(f"Il y a eu {nbr_e} 'e' dans cette phrase.")
5 - Lecture des éléments un à un (méthode nominative)

Cette gestion nominative d'itérer les éléments n'existe pas dans tous les langages.

Python ou Javascript l'utilisent et cela permet parfois d'avoir un code plus lisible, au détriment de la connaissance de l'index de l'élément en train d'être traité.

1 2 3 4 5 6 7 8 9
phrase1 = "bonjour, je suis la seconde façon de faire !" nbr_e = 0 for caractere in phrase1 : print(caractere) if caractere == 'e' : nbr_e = nbr_e + 1 print(f"Il y a eu {nbr_e} 'e' dans cette phrase.")

Ce programme affiche tout simplement les caractères un à un sans avoir à passer par un index dans le code :

b o n j o u r , j e s u i s l a s e c o n d e f a ç o n d e f a i r e ! Il y a eu 5 'e' dans cette phrase.

04° En utilisant la méthode du for nominatif, réaliser un programme qui demande à l'utilisateur de taper un texte et qui compte le nombre de e. Il affichera alors le résultat dans la console / shell Python.

Réaliser alors un programme qui compte les e, les a, les o et les i. Il affichera alors les résultats lettre par lettre.

...CORRECTION...

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
texte = input("Tapez la phrase que vous voulez analyser : ") nbr_a = 0 nbr_e = 0 nbr_i = 0 nbr_o = 0 for caractere in texte : if caractere == 'e' : nbr_e = nbr_e + 1 elif caractere == 'a' : nbr_a = nbr_a + 1 elif caractere == 'i' : nbr_i = nbr_i + 1 elif caractere == 'o' : nbr_o = nbr_o + 1 print(f"Il y a eu {nbr_e} 'e', {nbr_a} 'a', {nbr_i} 'i' et {nbr_o} 'o' dans cette phrase.")

Alors, for numérique ou for nominatif ?

Les deux.

Si vous n'avez pas besoin de connaître le numéro d'index de l'élément que vous examinez, utiliser un for nominatif sera plus lisible. Mais on pourrait utiliser la version avec index sans problème.

Par contre, si vous avez besoin de connaître le numéro d'index de l'élément que vous examinez, il faut utiliser un for numérique. Sinon, il vous faudra créer un compteur et l'augmenter de un à chaque tour de boucle. Autant prendre l'outil adapté non ?

6 - Non mutabilité des strings EN PYTHON

En Python, les strings sont non mutables (ou immuables) : cela veut dire qu'on ne peut pas modifier les lettres d'un contenu string après sa création.

>>> a = "bonjour" >>> a[0] = "d" TypeError: 'str' object does not support item assignment

D'autres langages se comportent comme Python : Java, C#, JavaScript...

Comment faire alors si on veut, mettons, changer les o minuscules en X majuscules ?

La solution : créer un nouveau string et l'affecter à une nouvelle variable qui porte le même nom que l'ancienne !

Attention : dans le code ci-dessous, le string est contenu avant et après dans une variable texte mais elle ne référence pas la même zone mémoire avant et après modification.

  • Avant modification, texte pointe vers l'identifiant-mémoire 12
  • Après modification, texte pointe vers l'identifiant-mémoire 18
String non mutable
Visualisation des modifications

VERSION avec INDEX numéroté (boucle "numérique")

1 2 3 4 5 6 7 8 9 10 11 12
texte = "bonjour" tempo = "" for index in range(len(texte)) : caractere = texte[index] if caractere == 'o' : tempo = tempo + 'X' else : tempo = tempo + caractere texte = tempo print(texte)

Voici le contenu modifié à chaque tour de boucle (lignes 4 à 9) de la variable tempo.

index contient 0, d'où : b index contient 1, d'où : bX index contient 2, d'où : bXn index contient 3, d'où : bXnj index contient 4, d'où : bXnjX index contient 5, d'où : bXnjXu index contient 6, d'où : bXnjXur

VERSION sans INDEX numéroté (boucle "nominative")

1 2 3 4 5 6 7 8 9 10 11
texte = "bonjour" tempo = "" for caractere in texte : if caractere == 'o' : tempo = tempo + 'X' else : tempo = tempo + caractere texte = tempo print(texte)

Voici le contenu modifié à chaque tour de boucle (lignes 4 à 8) de la variable tempo.

caractère contient "b", d'où : b caractère contient "o", d'où : bX caractère contient "n", d'où : bXn caractère contient "j", d'où : bXnj caractère contient "o", d'où : bXnjX caractère contient "u", d'où : bXnjXu caractère contient "r", d'où : bXnjXur

Dans d'autres langages (PHP, Ruby, C++...), le string est mutable : on peut changer directement la valeur d'un caractère.

✎ 05° Créer une fonction sans_accent qui possède un paramètre contenant un string. Elle doit renvoyer une copie de ce string en modifiant les "é", "ê" et "è" en un simple "e".

Voici son prototype :

1
def sans_accent(texte:str) -> str

Voici le code à modifier :

1 2 3
def sans_accent(texte) : '''Renvoie une copie de texte mais en remplacant les caractères accentués par une version non accentuée''' return texte

Utiliser la boucle for qui vous convient le mieux.

06° Modifier les lignes 19 et 20 de la fonction etoile_mystere (voir ci-dessous) qui renvoie un string de même taille que celui reçu en paramètre. Elle devra passer les tests automatiques en renvoyant les bonnes réponses attendues. La difficulté de la question tient donc autant à la compréhension de la demande (que doit faire la fonction ?) qu'à la façon de réaliser cela (comment coder ce qu'on lui demande de faire ?).

Voici son prototype :

1
def etoile_mystere(texte:str, numero:int) -> str

La réponse sera composée presque uniquement d'étoiles ("*").

Les points ('.'), les virgules (','), les espaces (' ') ainsi que le caractère de numéro d'index fourni en argument devront être inchangés. Voir la documentation pour d'autres exemples.

>>> etoile_mystere('Bonjour à toi !', 2) '**n**** * *** *'

Le principe de la fonction est de reconstruire un nouveau string en rajoutant un par un le nouveau caractère.

Comme on doit agir en fonction du numéro d'index, nous n'avons pas le choix, il faut utiliser un FOR numérique. Sinon, cela va complexifier encore plus le code.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
def etoile_mystere(texte, numero) : '''Renvoie un string composé d'étoiles. Seuls le caractère d'index fourni, le point, la virgule et les espaces sont inchangé ::param texte(str) :: le string qui sert de base de travail ::param numero(int) :: le numéro d'index du caractère qu'on ne veut pas modifier ::return (str) :: le string composé surtout d'étoiles >>> etoile_mystere('bonjour',1) '*o*****' >>> etoile_mystere('Bonjour à tous !', 2) '**n**** * **** *' ''' tempo = "" for index in range(len(texte)) : caractere = texte[index] if caractere == '.' or caractere == ',' or caractere == ' ' : # Gestion des caractères spéciaux tempo = tempo + caractere elif index == 1000 : # condition à modifier pass # à modifier aussi else : # Tous les autres cas tempo = tempo + '*' return tempo if __name__ == '__main__' : import doctest doctest.testmod() chaine = 'Bonjour à tous !' chaine = etoile_mystere(chaine,2) print(chaine)

Exemple si on utilise etoile_mystere("Bonjour à tous !",2)

  • Initialement, tempo = ""
  • Avec caractere = texte[0] = "B", on construit tempo = "*"
  • Avec caractere = texte[1] = "o", on construit tempo = "**"
  • Avec caractere = texte[2] = "n", on construit tempo = "**n"
  • Avec caractere = texte[3] = "j", on construit tempo = "**n*"
  • ...

Ligne 17 - Utilisation du or : Vous pouvez voir l'utilisation d'un OU (OR) qui permet de valider à True le test si l'une des conditions est vraie.

if caractere == '.' or caractere == ',' or caractere == ' ' : # Gestion des caractères spéciaux tempo = tempo + caractere

Cela permet d'alléger l'écriture en évitant la multitude de elif à la suite.

if caractere == '.' : # Gestion des caractères spéciaux tempo = tempo + caractere elif caractere == ',' : # Gestion des caractères spéciaux tempo = tempo + caractere elif caractere == ' ' : # Gestion des caractères spéciaux tempo = tempo + caractere

...CORRECTION...

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
def etoile_mystere(texte, numero) : '''Renvoie un string composé d'étoiles. Seuls le caractère d'index fourni, le point, la virgule et les espaces sont inchangé ::param texte(str) :: le string qui sert de base de travail ::param numero(int) :: le numéro d'index du caractère qu'on ne veut pas modifier ::return (str) :: le string composé surtout d'étoiles >>> etoile_mystere('bonjour',1) '*o*****' >>> etoile_mystere('Bonjour à tous !', 2) '**n**** * **** *' ''' tempo = "" for index in range(len(texte)) : caractere = texte[index] if caractere == '.' or caractere == ',' or caractere == ' ' : # Gestion des caractères spéciaux tempo = tempo + caractere elif index == numero : # Gestion du cas numéro d'index voulu tempo = tempo + caractere else : # Tous les autres cas tempo = tempo + '*' return tempo if __name__ == '__main__' : import doctest doctest.testmod() chaine = 'Bonjour à tous !' chaine = etoile_mystere(chaine,2) print(chaine)

Il s'agissait donc de votre premier contact avec la gestion des strings via les index.

Sur la gestion des strings, on utilise en programmation Python l'index numéroté ou le for nominatif en fonction des besoins. Si la solution nominative offre un code plus court et plus proche du langage humain, autant l'utiliser.

2 - Tableaux

Nous allons passer maintenant à une nouvelle structure de données qui ressemble par beaucoup d'aspects au string : le tableau.

Il possède deux différences notables :

  1. On peut y stocker d'autres choses que des caractères
  2. Il est mutable : on peut changer le contenu d'une case du tableau sans changer l'adresse mémoire de la variable-tableau
Tableau en informatique

Le mot tableau sera étudié plus en détail dans la partie DONNEES.

En informatique, un tableau est une structure de données ayant les propriétés suivantes :

  • La structure permet de stocker des données dans un nombre fixé de cases, défini lors de la déclaration initiale du tableau.
  • Chacune des cases contient le même type de données (soit des entiers sur 4 octets, soit des caractères, soit des entiers sur 2 octets, soit des floats sur 4 octets ...)

Voici deux exemples de tableaux 

Un tableau de caractéres de taille 3

Index Contenu
0 'A'
1 'B'
2 'C'

Un tableau de flottants de taille 4

Index Contenu
0 5.89
1 12.56
2 15.89
3 5.0

Nous allons voir maintenant comment un tableau s'utilise en Python.

1 - Déclaration d'un tableau en Python

Les éléments délimitateurs sont les crochets. Chaque élément du tableau est séparé des autres par une virgule.

Exemple

>>> table = ['a', 'b', 'c'] >>> table ['a', 'b', 'c'] >>> type(table) <class 'list'>

Comme vous pouvez le voir, le type natif de l'objet que nous utilisons pour gérer les tableaux statiques (arrays en anglais) dans Python se nomme list.

2 - Nombre d'éléments stockés

On peut utiliser la fonction native len pour obtenir le nombre d'éléments (ici des caractères pour le premier cas et des floats pour le deuxième cas) stockés dans le tableau.

Exemple

>>> tableau = ['a', 'b', 'c'] >>> nbr = len(tableau) >>> nbr 3 >>> type(tableau) <class 'list'>
>>> tableau = [12.45, 5.0, 17.9, 4.32] >>> nbr = len(tableau) >>> nbr 4 >>> type(tableau) <class 'list'>

On remarquera bien que dans les deux cas, nous avons le type natif list : on ne trouve pas d'indication directe sur le type des données contenues dans le tableau.

La variable tableau désigne ici le conteneur, pas le contenu.

07° Trouver (à l'aide d'un code Python) le nombre de notes de l'élève A à partir de t_notes_A et le nombre d'élèves dans la classe à partir de t_eleves :

Tableau 1

t_notes_A = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 13, 14] 

Phrase 2

t_eleves = ["Lisa", "Scott", "Matthias", "Antoine", "Ethan", "Lucas", "Manon", "Alexandre", "Alexandre", "Kenzo", "Thomas", "Lilou", "Aurélien", "Charles", "Manon", "Francia", "Imrane", "Sarah", "Yassin", "Sofian", "Noé", "Lenny", "Matt", "Ryiad", "Yanis", "Jason", "Damien", "Antonin", "Samy", "Laurine", "Rayan", "Eliot", "Victor", "Theo", "Julien", "Benjamin"] 

...CORRECTION...

1 2 3 4 5 6 7 8
t_notes_A = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 13, 14] t_eleves = ["Lisa", "Scott", "Matthias", "Antoine", "Ethan", "Lucas", "Manon", "Alexandre", "Alexandre", "Kenzo", "Thomas", "Lilou", "Aurélien", "Charles", "Manon", "Francia", "Imrane", "Sarah", "Yassin", "Sofian", "Noé", "Lenny", "Matt", "Ryiad", "Yanis", "Jason", "Damien", "Antonin", "Samy", "Laurine", "Rayan", "Eliot", "Victor", "Theo", "Julien", "Benjamin"] nbr_notes = len(t_notes_A) nbr_eleves = len(t_eleves) print(nbr_notes) print(nbr_eleves)

On obtient alors les réponses suivantes : 14 notes pour l'èlève A et 36 élèves au total.

3 - Accès à l'un des éléments

Pour accéder à l'un des éléments en particulier, on peut noter le nom de la variable suivi de crochets et y placer l'index du numéro voulu.

Exemple

>>> tableau = ['a', 'b', 'c'] >>> element_0 = tableau[0] >>> element_0 'a' >>> element_1 = tableau[1] >>> element_1 'b' >>> element_2 = tableau[2] >>> element_2 'c'

La correspondance index - élément donne ceci sur l'exemple

Index 0 1 2
Elément 'a' 'b' 'c'

On notera que l'index du premier élément porte le numéro d'index 0 et pas le numéro 1  !.

On notera également qu'on peut avoir accès à l'élément 5 sans avoir lu au préalable le 2,3 et 4. Ce n'est pas le cas pour toutes les structures de données.

08° L'encodage ASCII des caractères fait correspondre un nombre à quelques caractères.

Trouver le caractère ayant l'index 65 en utilisant le tableau t_ascii.

t_ascii = ['\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\t', '\n', '\x0b', '\x0c', '\r', '\x0e', '\x0f', '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', ' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '\x7f']

...CORRECTION...

1 2
t_ascii = ['\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\t', '\n', '\x0b', '\x0c', '\r', '\x0e', '\x0f', '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', ' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '\x7f'] print(t_ascii[65])
4 - Lecture des éléments un à un via l'index (méthode classique par boucle numérique)

On peut aussi lire les éléments un par un en utilisant une boucle FOR couplée à la fonction len pour connaitre la valeur limite à placer pour l'indice d'incrémentation de la boucle.

Ainsi avec

 t_notes_A = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] 

Nous avons 14 éléments avec un index 0-1-2-3-4-5-6-7-8-9-10-11-12-13.

Index 0 1 2 3 4 5 6 7 8 9 10 11 12 13
Elément 15 18 8 10 12 15 20 5 12 17 12 10 18 4

Il faudrait donc utiliser for index in range(14) :

Exemple

1 2 3 4 5
notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] nbr = len(notes) for index in range(nbr) : print(notes[index])

Ce programme va afficher ceci dans la console :

15 18 8 10 12 15 20 5 12 17 12 10 18 4

Si on désire les voir s'afficher en les séparant par un tiret, on peut utiliser ceci :

1 2 3 4 5
notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] nbr = len(notes) for index in range(nbr) : print(notes[index], end="-")

On obtient alors ceci

15-18-8-10-12-15-20-5-12-17-12-10-18-4-

09° Réaliser un court programme qui affiche les notes en notant "1er Trimestre : " pour les notes dont l'index est dans l'intervalle [0;9], c'est à dire de 0 inclus à 9 inclus, "2e Trimestre : " pour les notes dont l'index est dans l'intervalle [10;19] et "3e Trimestre : " pour les notes dont l'index est supérieur à 20.

notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4]

Vous devriez donc obtenir quelque chose qui ressemble à ceci :

1er Trimestre : 15 1er Trimestre : 18 1er Trimestre : 8 1er Trimestre : 10 1er Trimestre : 12 1er Trimestre : 15 1er Trimestre : 20 1er Trimestre : 5 1er Trimestre : 12 1er Trimestre : 17 2e Trimestre : 12 2e Trimestre : 10 2e Trimestre : 18 2e Trimestre : 4

...CORRECTION...

1 2 3 4 5 6 7 8 9
notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] for index in range(len(notes)) : if index < 10 : print(f"1er Trimestre : {notes[index]}") elif index < 20 : print(f"2e Trimestre : {notes[index]}") else : print(f"3e Trimestre : {notes[index]}")
5 - Lecture des éléments un à un (méthode nominative)

Cette gestion nominative d'itérer les éléments n'existe pas dans tous les langages.

1 2 3 4 5 6 7 8 9
notes = [15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4] for element in notes : if element > 12 : print("Bien : ", element) elif element < 8 : print("Pas bien : ", element) else : print("Moyen : ", element)

Ce programme affiche "Bien", "Pas bien" ou "Moyen" devant chaque note sans avoir à passer par un index dans le code :

Bien : 15 Bien : 18 Moyen : 8 Moyen : 10 Moyen : 12 Bien : 15 Bien : 20 Pas bien : 5 Moyen : 12 Bien : 17 Moyen : 12 Moyen : 10 Bien : 18 Pas bien : 4

Alors, for numérique ou for nominatif ?

Les deux.

Si vous n'avez pas besoin de connaître le numéro d'index de l'élément que vous examinez, utiliser un for nominatif sera plus lisible. Mais on pourrait utiliser la version indexée sans problème.

Si vous avez besoin de connaître le numéro d'index de l'élément que vous examinez, utiliser un for numérique sera facile.

6 - Modifier un tableau : mutabilité / muabilité des tableaux dans Python

Dans la majorité des langages, les tableaux sont mutables (anglissisme, on dira muable en français) : cela veut dire qu'on peut modifier les contenus d'un tableau après sa création. On dit qu'on peut modifier l'état du tableau.

En Python, le type list est mutable. Nous considérerons donc que les tableaux sont mutables lors de notre utilisation de Python.

>>> tableau = ['a', 'b', 'c'] >>> tableau ['a', 'b', 'c'] >>> tableau[0] = 'Z' >>> tableau ['Z', 'b', 'c']

Avantage (ou désavantage !) concret de mettre du contenu dans un tableau ? On peut modifier l'état du tableau (son contenu) depuis une fonction : le nom de la variable ne sert qu'à localiser l'adresse-mémoire menant au tableau.

Avant la modification : tableau mène à l'id 12 et tableau[0] à l'id 40
Tableau mutable
Après la modification : tableau mène toujours à l'id 12 mais tableau[0] à l'id 48
Tableau mutable

✎ 10° Réaliser un court programme qui transformera les notes contenus dans un tableau fourni en début de programme. Les notes initialement supérieures ou égales à 10 sont transformées en 20. Les notes inférieures à 10 sont transformées en 0.

Exemple AVANT / APRES :

[12, 10, 5, 2, 12]
[20, 20, 0, 0, 20]

Jusqu'à présent, vous ne savez créer des tableaux qu'en déclaration : on note dans les crochets les valeurs voulues. Pour créer un tableau contenant les entiers de 1 à 3000, ca risque d'être long à taper...

7 - Déclaration de tableau par compréhension à partir d'un tableau initial

La déclaration d'un tableau par compréhension est celle qui consiste à formuler le contenu du tableau directement dans les crochets à l'aide d'une boucle for.

reponses = [None for valeur in entree]
>>> tab1 = [1, 2, 3] >>> sortie = [None for valeur in tab1] >>> sortie [None, None, None]

En réalité, on peut faire mieux que mettre None dans chaque case : on peut indiquer le calcul à faire directement !

Si on veut un tableau contenant exactement le double du tableau précédent, on peut faire ceci :

reponses = [valeur * 2 for valeur in entree]
>>> tab1 = [1, 2, 3] >>> sortie = [valeur*2 for valeur in tab1] >>> sortie [2, 4, 6]

C'est beaucoup plus simple à écrire qu'avec un for. En réalité, l'interpréteur Python réalise en arrière plan la boucle for.

8 - Déclaration de tableau par compréhension avec un range

On peut également créer des tableaux contenant un nombre précis d'élements de façon assez facile : il suffit d'utliser range.

>>> tableau = [0 for valeur in range(10)] >>> tableau [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> tableau = [valeur*10 for valeur in range(10)] >>> tableau [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
>>> import random >>> tableau = [random.randint(1,100) for valeur in range(10)] >>> tableau [42, 41, 96, 35, 58, 94, 16, 21, 84, 51]

✎ 11° Créer par compréhension un tableau de 20 éléments contenant de nombres aléatoires compris entre 20 et 50.

✎ 12° Créer par compréhension un tableau de 500 éléments contenant 0.

On peut même faire mieux : on peut inclure des tests ou des fonctions dans la construction.

Premier exemple : on crée un tableau de 50 éléments compris entre 0 et 20. On crée un second tableau à partir du premier : on ne garde que les nombres supérieurs ou égaux à 10.

>>> import random >>> tableau = [random.randint(0,20) for valeur in range(50)] >>> tableau_2 = [note for note in tableau if note >= 10] >>> tableau [12, 8, 1, 3, 3, 17, 8, 2, 2, 10, 15, 3, 16, 13, 5, 18, 12, 15, 19, 10, 9, 14, 0, 15, 11, 6, 11, 1, 10, 6, 17, 3, 17, 10, 9, 8, 1, 9, 7, 12, 15, 10, 15, 15, 9, 8, 18, 8, 9, 6] >>> tableau_2 [12, 17, 10, 15, 16, 13, 18, 12, 15, 19, 10, 14, 15, 11, 11, 10, 17, 17, 10, 12, 15, 10, 15, 15, 18]

On peut enfin utiliser des fonctions lors de la création. Imaginons qu'on dispose de cette fonction en mémoire :

1 2 3 4 5
def pas_plus(valeur, seuil) : '''Fonction qui renvoie la valeur ou le seuil si la valeur est supérieure au seuil''' if valeur > seuil : return seuil return valeur
>>> import random >>> tableau = [pas_plus(random.randint(0,20), 15) for valeur in range(10)] >>> tableau [14, 15, 7, 14, 11, 1, 13, 12, 15, 1]

On obtient bien un tableau de 10 éléments sans qu'aucun élément ne soit plus grand que 15.

C'est tout pour le premier contact avec les tableaux, qu'on implémente en Python à l'aide des list.

Pour informations, sachez qu'une list Python n'a pas nécessairement besoin que les éléments qu'on y place soient tous de même nature. Mais comme nous les utiliserons comme des tableaux (présents dans tous les langages), nous nous limiterons au cas d'éléments de même nature.

On pourrait créer une list Python contenant ceci :
exemple = [1, 1.55, 'bonjour']
Mais dans ce cas, nous ne dirons pas qu'exemple est un tableau.

3 - P-uplets

Dernière structure de données que nous allons survoler ici : le p-uplets de valeurs.

Il s'agit d'une structure ordonnée de X élements 

  • Permettant de stocker des données de natures différentes (contrairement aux strings ou aux tableaux)
  • Indexable par un numéro (comme les strings et les tableaux)

Comme il s'agit d'une structure non mutable en Python, on l'utilise beaucoup lorsqu'on veut transmettre des données sans qu'elles ne puissent être modifiées.

1 - Déclaration d'un p-uplet en Python

En anglais, on dira tuple.

Les éléments délimitateurs sont les parenthèses. Chaque élément du p-uplet est séparé des autres par une virgule.

Exemple avec un p-uplet contenant le nom du produit, le nombre en stock et le prix à l'unité.

>>> exemple = ('Ananas', 60, 2.20) >>> exemple ('Ananas', 60, 2.20) >>> type(exemple) <class 'tuple'>

Attention, si vous voulez créer un p-uplet ne contenant qu'un seul élément, il faudra placer une virgule après le premier élément. Sinon, l'interpréteur Python croira qu'il s'agit juste de parenthèses.

Exemple à ne pas faire si vous voulez un tuple

>>> exemple = ('Ananas') >>> exemple 'Ananas' >>> type(exemple) <class 'str'>

Exemple à faire si vous voulez un tuple

>>> exemple = ('Ananas' ,) >>> exemple ('Ananas',) >>> type(exemple) <class 'tuple'>
2 - Nombre d'éléments stockés

On peut utiliser la fonction native len pour obtenir le nombre d'éléments stockés dans le p-uplet.

Exemple

>>> exemple = ('Ananas', 60, 2.20) >>> nbr = len(table) >>> nbr 3

On peut nommer

  • couple ou doublet un p-uplet de 2 éléments
  • triplet un p-uplet de 3 éléments
  • quadruplet un p-uplet de 4 éléments
  • quintuplet un p-uplet de 5 éléments
  • ...
3 - Accès à l'un des éléments

Pour accéder à l'un des éléments en particulier, on peut noter le nom de la variable suivi de crochets et y placer l'index du numéro voulu.

Exemple

>>> exemple = ('Ananas', 60, 2.20) >>> element_0 = exemple[0] >>> element_0 'Ananas' >>> element_1 = exemple[1] >>> element_1 60 >>> element_2 = exemple[2] >>> element_2 2.2

La correspondance index - élément donne ceci sur l'exemple

Index 0 1 2
Elément 'Ananas' 60 2.2

On notera que l'index du premier élément porte le numéro d'index 0 et pas le numéro 1  !.

4 - Lecture des éléments un à un par l'index (méthode classique avec boucle numérique)

On peut aussi lire les éléments un par un en utilisant une boucle FOR couplée à la fonction len pour connaitre la valeur limite à placer pour l'indice d'incrémentation de la boucle.

Ainsi avec

 t_notes_A = (15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4) 

Nous avons 14 éléments avec un index 0-1-2-3-4-5-6-7-8-9-10-11-12-13.

Index 0 1 2 3 4 5 6 7 8 9 10 11 12 13
Elément 15 18 8 10 12 15 20 5 12 17 12 10 18 4

Il faudrait donc utiliser for index in range(14) :

Exemple

1 2 3 4 5
notes = (15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4) nbr = len(notes) for index in range(nbr) : print(notes[index])

Ce programme va afficher ceci dans la console :

15 18 8 10 12 15 20 5 12 17 12 10 18 4

Si on désire les voir s'afficher en les séparant par un tiret, on peut utiliser ceci :

1 2 3 4 5
notes = (15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4) nbr = len(notes) for index in range(nbr) : print(notes[index], end="-")

On obtient alors ceci

15-18-8-10-12-15-20-5-12-17-12-10-18-4-

On remarquera qu'il s'agit des mêmes exemples qu'avec les tableaux. L'unique différence vient ici de l'utilisation de parenthèses plutôt que de crochets lors de la déclaration.

5 - Lecture des éléments un à un (méthode nominative)

Cette gestion nominative d'itérer les éléments n'existe pas dans tous les langages.

1 2 3 4 5 6 7 8 9
notes = (15, 18, 8, 10, 12, 15, 20, 5, 12, 17, 12, 10, 18, 4) for element in notes : if element > 12 : print("Bien : ", element) elif element < 8 : print("Pas bien : ", element) else : print("Moyen : ", element)

Ce programme affiche "Bien", "Pas bien" ou "Moyen" devant chaque note sans avoir à passer par un index dans le code :

Bien : 15 Bien : 18 Moyen : 8 Moyen : 10 Moyen : 12 Bien : 15 Bien : 20 Pas bien : 5 Moyen : 12 Bien : 17 Moyen : 12 Moyen : 10 Bien : 18 Pas bien : 4
6 - Non mutabilité / Immuabilité des tuples EN PYTHON

En Python, les tuples sont non mutables (anglissisme) ou immuables (en français véritable) : cela veut dire qu'on ne peut pas modifier le contenu après sa création. On dit qu'on ne peut pas modifier l'état du tuple placé en mémoire.

>>> produit = ('Ananas', 60, 2.2) >>> produit[1] = 50 TypeError: 'tuple' object does not support item assignment

Nous allons voir maintenant les deux utilisations courantes des tuples 

  • Retour de plusieurs données (qu'on ne veut pas pouvoir modiifier par inadvertance) par une fonction
  • Volonté de transmettre une donnée non mutable / immuable

Voici un programme qui possède une fiche d'enregistrement sur un produit : son nom ('Jeu vidéo de la mort qui tue'), le nombre vendu (103) et la marge de bénéfice sur chaque vente (20.3).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
def fournir_fiche_marge(fiche_produit): '''Fonction qui renvoie un tuple-enregistrement contenant le nom du produit et le bénéfice sur ce produit (nbr*marge) ::param fiche_produit(str,int,float) :: le nom du produit, nombre vendu et marge sur chaque vente ::return (str, float) :: tuple contenant le nom du produit et la marge qu'il a ramené >>> fournir_fiche_marge(("Voiture électrique", 100, 5.0)) ('Voiture électrique', 500.0) ''' return ('vide', 0) if __name__ == '__main__' : import doctest doctest.testmod() fiche_produit_1 = ('Jeu vidéo de la mort qui tue', 103, 20.3) fiche_marge = fournir_fiche_marge(fiche_produit_1)

13° Lors de l'appel de la ligne 17, que va contenir le paramètre fiche_produit de la fonction ? Que contient alors fiche_produit[2] ?

...CORRECTION...

L'argument envoyé étant fiche_produit_1, on va avoir fiche_produit = fiche_produit_1 = ('Jeu vidéo de la mort qui tue', 103, 20.3)

On voit que fiche_produit_1[0] va renvoyer 'Jeu vidéo de la mort qui tue'.

On voit donc que fiche_produit_1[2] va renvoyer 20.3.

14° Modifier la fonction pour qu'elle fasse le travail qu'on lui demande de faire : calculer le bénéfice sur la vente du produit et renvoyer un tuple contenant les bonnes informations (voir les lignes 7/8 de la documentation).

...CORRECTION...

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
def fournir_fiche_marge(fiche_produit): '''Fonction qui renvoie un tuple-enregistrement contenant le nom du produit et le bénéfice sur ce produit (nbr*marge) ::param fiche_produit(str,int,float) :: le nom du produit, nombre vendu et marge sur chaque vente ::return (str, float) :: tuple contenant le nom du produit et la marge qu'il a ramené >>> fournir_fiche_marge(("Voiture électrique", 100, 5.0)) ('Voiture électrique', 500.0) ''' nom = fiche_produit[0] marge_totale = fiche_produit[1] * fiche_produit[2] return (nom, marge_totale) if __name__ == '__main__' : import doctest doctest.testmod() fiche_produit_1 = ('Jeu vidéo de la mort qui tue', 103, 20.3) fiche_marge = fournir_fiche_marge(fiche_produit_1)

15° Que va afficher le programme si on rajoute la ligne 20 suivante  :?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
def fournir_fiche_marge(fiche_produit): '''Fonction qui renvoie un tuple-enregistrement contenant le nom du produit et la marge totale (nbr*marge) ::param fiche_produit(str,int,float) :: le nom du produit, nombre vendu et marge sur chaque vente ::return (str, float) :: tuple contenant le nom du produit et la marge qu'il a ramené >>> fournir_fiche_marge(("Voiture électrique", 100, 5.0)) ('Voiture électrique', 500.0) ''' nom = fiche_produit[0] marge_totale = fiche_produit[1] * fiche_produit[2] return (nom, marge_totale) if __name__ == '__main__' : import doctest doctest.testmod() fiche_produit_1 = ('Jeu vidéo de la mort qui tue', 103, 20.3) fiche_marge = fournir_fiche_marge(fiche_produit_1) print(fiche_marge[1])

16° Que va afficher l'interpréteur si on tape fiche_marge[1] = 200 dans le Shell ?

...CORRECTION...

Une erreur : le tuple est une structure non mutable en Python.

On peut également récupérer directement les données d'une fonction renvoyant un tuple : il suffit de stocker le résultat dans un ensemble de variables, plutôt que dans un tuple directement.

✎ 17° Que va afficher le programme si on utilise les lignes 19 et 20 suivantes :?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
def fournir_fiche_marge(fiche_produit): '''Fonction qui renvoie un tuple-enregistrement contenant le nom du produit et la marge totale (nbr*marge) ::param fiche_produit(str,int,float) :: le nom du produit, nombre vendu et marge sur chaque vente ::return (str, float) :: tuple contenant le nom du produit et la marge qu'il a ramené >>> fournir_fiche_marge(("Voiture électrique", 100, 5.0)) ('Voiture électrique', 500.0) ''' nom = fiche_produit[0] marge_totale = fiche_produit[1] * fiche_produit[2] return (nom, marge_totale) if __name__ == '__main__' : import doctest doctest.testmod() fiche_produit_1 = ('Jeu vidéo de la mort qui tue', 103, 20.3) (nom , marge) = fournir_fiche_marge(fiche_produit_1) print(marge)

Les parenthèses ne sont pas obligatoires mais permettent de bien comprendre que la fonction renvoie un tuplet. Nous aurions donc eu le même résultat avec la ligne suivante 

nom , marge = fournir_fiche_marge(fiche_produit_1)

Mais on perd l'indication que la fonction envoie un tuple. C'est bien visible avec la version proposée : on voit bien que la fonction ne renvoie qu'une seule donnée mais que cette donnée est un tuple.

(nom , marge) = fournir_fiche_marge(fiche_produit_1)

4 - transformation de l'un en l'autre

Nous venons de voir que les structures de données ont des avantages et des inconvénients.

En Python, si on veut qu'une fonction puisse modifier les données stockées, il faut utiliser un tableau par exemple.

Si par contre, on veut juste fournir des valeurs, autant utiliser un tuple qui évitera ainsi que quelqu'un les modifie par erreur.

Mais comment passer de l'un à l'autre ?

En utilisant les fonctions natives permettant de le faire :

  • str tente de transformer les données fournies en une string
  • list tente de transformer les données fournies en un tableau (list)
  • tuple tente de transformer les données fournies en un p-uplet (tuple)

18° Exécuter les commandes suivantes dans le Shell pour comprendre l'action de ces trois fonctions

En partant d'un string

>>> chaine = "abc" >>> chaine 'abc' >>> tableau = list(chaine) >>> tableau ['a', 'b', 'c'] >>> puplet = tuple(chaine) >>> puplet ('a', 'b', 'c')

En partant d'un tableau

>>> tableau = ['a','b','c'] ['a', 'b', 'c'] >>> chaine = str(tableau) >>> chaine "['a', 'b', 'c']" >>> puplet = tuple(tableau) >>> puplet ('a', 'b', 'c')

En partant d'un tuple

>>> puplet = ('a','b','c') ('a', 'b', 'c') >>> chaine = str(puplet) >>> chaine "('a', 'b', 'c')" >>> tableau = list(puplet) >>> tableau ['a', 'b', 'c']

Une dernière remarque pour la fin

Comment trouver le nombre de mots dans une phrase ?

En utilisant simplement une fonction maison ou en utilisant la méthode split des strings.

Cette méthode crée une liste à partir d'un string. Comment ? En divisant le string à l'aide d'un élément délimitateur. Par défaut, il s'agit de l'espace.

>>> phrase = "Voici un exemple de phrase, il permet de compter les mots." >>> mots = phrase.split() >>> mots ['Voici', 'un', 'exemple', 'de', 'phrase,', 'il', 'permet', 'de', 'compter', 'les', 'mots.'] >>> nbr_mots = len(mots) >>> nbr_mots 11

Bien entendu, il reste encore quelques détails à régler, comme supprimer les points et les virgules. Mais il faut bien que vous fassiez deux trois choses pendant vos projets !

Nous avons vu ici 

  • Strings, tuples et tableaux
  • Les and et les or pour regrouper les tests booléens

Nous sommes maintenant assez armés pour réaliser de vrais programmes gérant les données de façon automatisée.

Et partir sur les premiers vrais projets de groupe.

Des informations supplémentaires dans la partie FICHES, dont

Activité publiée le 01 11 2019
Dernière modification : 19 07 2020
Auteur : ows. h.