python index num

Identification

Infoforall

12 - 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-13-15

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 (méthode classique)

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.

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 devrirez 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, de a, de o et de i. Il affichera alors les résultats.

...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 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 forn numérique sera facile. Mais on pourrait utiliser la version nominative sans problème : il faudra réimplanter une numérotation en se créant à la main un compteur. Ce n'est pas le plus rentable à faire.

6 - Non mutabilité des strings EN PYTHON

En Python, les strings sont non mutables : cela veut dire qu'on ne peut pas modifier les lettres d'un contenu string après sa création. On dit qu'on ne peut pas modifier l'état du string placé en mémoire.

>>> 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 contenu string et l'affecter à une nouvelle variable portant le même nom que l'ancienne variable !

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

Attention : après nos boucles, le nouveau texte porte le même nom (alias) mais la référence mémoire ne sera plus la même : ouf. Le string reste donc une entité immutable. La nouvelle variable est bien une NOUVELLE variable ayant presque le même contenu.

String non mutable
Visualisation des modifications

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".

Utiliser la boucle for qui vous convient le mieux.

06° Compléter la fonction etoile_mystere (voir ci-dessous) qui renvoie un string de même taille que celui reçu en paramètre.

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

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

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

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*"
  • ...

Votre travail est de modifier les lignes 19 et 20.

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
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)

...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 de l'objet que nous utilisons pour gérer les tableaux (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 des types 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 (méthode classique)

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]

...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]}")

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
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 forn numérique sera facile. Mais on pourrait utiliser la version nominative sans problème : il faudra réimplanter une numérotation en se créant à la main un compteur. Ce n'est pas le plus rentable à faire.

6 - Mutabilité des tableaux dans Python

Dans la majorité des langages, les tableaux sont mutables : 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 sans avoir besoin de mettre le mot clé global : le nom de la variable ne sert qu'à localiser l'adresse-mémoire menant à l'index.

Avant la modification :
Tableau mutable
Après la modification : tableau est toujours associé à Id12
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]

Nous allons maintenant voir un point important : l'interaction entre les fonctions et les contenus mutables.

Imaginons que nous ayons à gérer un jeu où le personnage est défini par trois jauges.

  • Le nombre de points de vie est stocké à l'index 0.
  • Le nombre de points de magie est stocké à l'index 1.
  • Le nombre de points de chance est stocké à l'index 2.

jauges = [50, 60, 80] veut dire

  • 50 points de vie
  • 60 points de magie
  • 80 points de chance

Nous allons déclarer une fonction diminuer_une_jauge, fonction dont voici le prototype :

def diminuer_une_jauge(jauges, degats, index) :

On lui fournit donc le tableau jauges à lire et modifier, la valeur des degats à soustraire et l'index de la jauge qui doit diminuer.

La fonction doit renvoyer True si la jauge est toujours positive après diminution.

Exemple d'utilisation :

>>> jauges = [50, 60, 80] >>> diminuer_une_jauge(jauges, 40, 1) True >>> jauges [50, 20, 80]

On a bien diminuer la jauge d'index 1 qui valait 60 initialement.

✎ 11° Cas théorique : que va afficher la console Python lorsqu'on lui demande de fournir le contenu de la variable lePersonnage ?

>>> lePersonnage = [50, 40, 30] >>> diminuer_une_jauge(lePersonnage, 40, 0) True >>> lePersonnage

12° QCM : Sans lancer le programme (qui est non fonctionnel pour l'instant), lire uniquement la documentation de la fonction diminuer_une_jauge et donner le contenu que devra avoir le tableau [5, 2, 10] après exécution de la ligne 12.

  • A : [0, 2, 10]
  • B : [5, -3, 5]
  • C : [5, 2, 5]
  • D : [0, 0, 10]

Faire de même pour la ligne 14.

  • A : [-1, 2, 10]
  • B : [5, -4, 5]
  • C : [5, 2, 4]
  • D : [0, 0, 10]
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 31 32 33 34
def diminuer_une_jauge(jauges, degats, index) : '''Fonction qui modifie jauges[index] en lui enlevant degats si possible La fonction renvoie : False si la jauge voulue est devenue négative, nulle ou que l'index n'existe pas True si la jauge est toujours positive après retrait des dégâts ::param jauges(list) :: le tableau contenant les jauges qu'on désire gérer ::param degats(int) :: le nombre voulu de dégâts à enlever ::param index(int) :: l'index voulu du tableau jauges ::return (bool) :: True si positif et possible, False sinon >>> diminuer_une_jauge([5,2,10], 5, 0) False >>> diminuer_une_jauge([5,2,10], 6, 2) True >>> diminuer_une_jauge([5,2,10], 6, 0) False >>> diminuer_une_jauge([5,2,10], 2, 4) False ''' return False if __name__ == '__main__' : import doctest doctest.testmod() jauges_perso_1 = [50, 60, 80] print(jauges_perso_1) disponible = diminuer_une_jauge(jauges_perso_1, 40, 1) if disponible == False : print("Personnage indisponible pour le moment") else : print("Personnage ok pour le moment.") print(jauges_perso_1)

...CORRECTION...

Après la ligne 12 (diminuer_une_jauge([5,2,10], 5, 0)), le tableau devrait contenir ceci 

[0,2,10] puisqu'on tente de diminuer de 5 points la jauge d'index 0.

La fonction va donc renvoyer False puisque la jauge est devenue nulle.

Après la ligne 14 (diminuer_une_jauge([5,2,10], 6, 2)), le tableau devrait contenir ceci 

[5,2,4] puisqu'on tente de diminuer de 6 points la jauge d'index 2.

La fonction va donc renvoyer True puisque la jauge est toujours positive.

La première chose à faire dans diminuer_une_jauge est de vérifier que l'index fourni par l'utilisateur correspond bien à un index valide. En effet, la seule précondition sur ce paramètre est qu'il doit être un integer. Si l'utilisateur envoie 10000, il a le droit d'après la documentation.

Pour cela, il faudra effectuer deux tests imbriqués l'un dans l'autre. Le premier vérifie que l'index est bien supérieur ou égal à 0. Le deuxième vérifie que l'index est bien strictement inférieur au nombre d'éléments contenus dans le tableau.

1 2 3 4 5
nombre = len(jauges) # Nombre de jauges différentes dans le tableau # Vérification de la validité de l'index if index >= 0 : if index < nombre : # Index valide pass # Les trucs à faire

C'est un peu lourd. Nous avons vu le OU (OR en anglais), et bien voyons le ET (AND en anglais) : pour que le test soit valide, il faut que les deux conditions soient VRAIES en même temps :

1 2 3 4
nombre = len(jauges) # Nombre de jauges différentes dans le tableau # Vérification de la validité de l'index if index >= 0 and index < nombre : # Index valide pass # Les trucs à faire

Ainsi si le tableau contient 3 éléments, les index valides sont bien 0-1-2 mais pas 3 ou 4.

✎ 13° La fonction diminuer_une_jauge fournie ci-dessous ne teste pour l'instant que la validité du paramètre index par rapport aux index disponibles pour le paramètre jauges.

Dans ce cadre, la jauge voulue est donc contenue dans jauges[index].

Remplacer maintenant la ligne 25 pour plusieurs autres lignes de façon à réaliser ceci :

    SI la jauge voulue est initialement > 0

      On diminue cette jauge de la quantité degats

      SI la jauge est toujours > 0 après diminution

        Renvoyer True

      SINON

        Renvoyer False

      Fin SI

    SINON

      Renvoyer False

    Fin SI

Vos modifications devront passer les doctests insérés.

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 31 32 33 34 35 36 37 38 39
def diminuer_une_jauge(jauges, degats, index) : '''Fonction qui modifie jauges[index] en lui enlevant degats si possible La fonction renvoie : False si la jauge voulue est devenue négative, nulle ou d'index impossible True si la jauge est toujours positive après retrait des dégâts ::param jauges(list) :: le tableau contenant les jauges qu'on désire gérer ::param index(int) :: l'index voulu du tableau jauges ::param degats(int) :: le nombre voulu de dégâts à enlever ::return (bool) :: True si c'est positif et possible, False sinon >>> diminuer_une_jauge([5,2,10], 5, 0) False >>> diminuer_une_jauge([5,2,10], 6, 2) True >>> diminuer_une_jauge([5,2,10], 6, 0) False >>> diminuer_une_jauge([5,2,10], 2, 4) False ''' nombre = len(jauges) # Nombre de jauges différentes # Vérification de la validité de l'index if index >= 0 and index < nombre : # Index valide return True # Ecrire des lignes et modifier pour répondre à la question else : return False if __name__ == '__main__' : import doctest doctest.testmod() jauges_perso_1 = [50, 60, 80] print(jauges_perso_1) disponible = diminuer_une_jauge(jauges_perso_1, 40, 1) if disponible == False : print("Personnage indisponible pour le moment") else : print("Personnage ok pour le moment.") print(jauges_perso_1)

Votre code est-il bon ? En réalité, votre doctest ne teste que la valeur True ou False renvoyée.
Si ça tombe, les modifications sur le tableau sont fausses, mais les tests fournis ne le détectent pas.

7 - Fonction à effet de bord

En informatique, une fonction est dite à effet de bord si elle modifie l'état d'une structure de données non locale à la fonction elle-même. C'est le cas de la fonction diminuer_une_jauge : elle va modifier l'état du tableau qu'on a fourni.

L'appel envoie la référence du tableau jauges_perso_1 :

validation = diminuer_une_jauge(jauges_perso_1, 40, 1)

Le prototype de la fonction permet de voir que cette référence va être stockée dans le paramètre-tableau jauges. Du coup, la variable-paramètre jauges fait référence à la même zone mémoire que jauges_perso_1.

Ensuite, on utilise cette référence pour modifier les valeurs stockées dans le tableau mais pas l'adresse du paramètre-tableau jauges en lui-même : jauges[index] = jauges[index] - nombre.

Exemple avec un paramètre contenant la zone-mémoire référencée par un identifiant de 12, contenant [5, 2, 10].

Dans les deux cas, jauges_perso_1[0] et jauges[0] pointent vers la valeur 5.

Avant la modification
Visualisation avant modification
Avant la modification
Visualisation après jauges[0] = jauges[0] - 5

Du coup, on modifie bien les éléments situées à l'adresse-mémoire de jauges_perso_1 !

Documentation : les effets de bords sont à signaler dans la documentation de vos fonctions. Il vaut mieux prévenir les autres que votre fonction va modifier le contenu d'un des paramètres, non ?

Bon, comment vérifier que votre code fonctionne ?
En fournissant de bons tests ! Lors des tests, nous allons fournir des tableaux à la fonction, vérifier sa réponse et demander à voir le contenu du tableau après application de la fonction.

14° Observer les docstests puis modifier la nouvelle fonction diminuer_une_jauge en remettant vos modifications. Relancer les tests. Cette fois, si votre code est bon, les tests vous le diront : les tests intégrent l'effet de bord que nous avions "oublié"" de signaler dans la documentation.

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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
def diminuer_une_jauge(jauges, degats, index) : '''Fonction qui modifie la jauge d'index fourni en lui enlevant degats si possible La fonction renvoie : False si la jauge voulue est devenue négative, nulle ou d'index impossible True si la jauge est toujours positive après retrait des dégâts ::param jauges(list) :: le tableau contenant les jauges qu'on désire gérer ::param index(int) :: l'index voulu du tableau jauges ::param degats(int) :: le nombre voulu de dégâts à enlever ::return (bool) :: True si c'est positif et possible, False sinon ..effet de bord :: le tableau jauges risque d'être modifié >>> tableau_test = [5, 2, 10] >>> diminuer_une_jauge(tableau_test, 5, 0) False >>> tableau_test [0, 2, 10] >>> tableau_test = [5, 2, 10] >>> diminuer_une_jauge(tableau_test, 6, 2) True >>> tableau_test [5, 2, 4] >>> tableau_test = [5, 2, 10] >>> diminuer_une_jauge(tableau_test, 6, 0) False >>> tableau_test [-1, 2, 10] >>> tableau_test = [5, 2, 10] >>> diminuer_une_jauge(tableau_test, 2, 4) False >>> tableau_test [5, 2, 10] ''' nombre = len(jauges) # Nombre de jauges différentes dans le tableau # Vérification de la validité de l'index if index >= 0 and index < nombre : # Index valide return True # A modifier else : return False if __name__ == '__main__' : import doctest doctest.testmod() jauges_perso_1 = [50, 60, 80] print(jauges_perso_1) disponible = diminuer_une_jauge(jauges_perso_1, 40, 1) if disponible == False : print("Personnage indisponible pour le moment") else : print("Personnage ok pour le moment.") print(jauges_perso_1)

...CORRECTION...

Attention, la correction n'est pas le reflet exact de la demande des questions précédentes. Ne l'utilisez pas pour faire semblant d'avoir trouvé !

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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
def diminuer_une_jauge(jauges, degats, index) : '''Fonction qui modifie jauges[index] en lui enlevant degats si possible La fonction renvoie : False si la jauge voulue est devenue négative, nulle ou d'index impossible True si la jauge est toujours positive après retrait des dégâts ::param jauges(list) :: le tableau contenant les jauges qu'on désire gérer ::param index(int) :: l'index voulu du tableau jauges ::param degats(int) :: le nombre voulu de dégâts à enlever ::return (bool) :: True si c'est positif et possible, False sinon .effet de bord :: le tableau jauges risque d'être modifié >>> tableau_test = [5, 2, 10] >>> diminuer_une_jauge(tableau_test, 5, 0) False >>> tableau_test [0, 2, 10] >>> tableau_test = [5, 2, 10] >>> diminuer_une_jauge(tableau_test, 6, 2) True >>> tableau_test [5, 2, 4] >>> tableau_test = [5, 2, 10] >>> diminuer_une_jauge(tableau_test, 6, 0) False >>> tableau_test [-1, 2, 10] >>> tableau_test = [5, 2, 10] >>> diminuer_une_jauge(tableau_test, 2, 4) False >>> tableau_test [5, 2, 10] ''' nombre = len(jauges) # Nombre de jauges différentes # Vérification de la validité de l'index if index >= 0 and index < nombre : # Index valide if jauges[index] <= 0 : # La jauge est déjà négative return False else : # Sinon, c'est que la jauge est supérieure à 0 jauges[index] = jauges[index] - degats if jauges[index] > 0 : # Il reste des points dans la jauge return True else : return False else : # Sinon, c'est que l'index n'est pas un entier valide return False if __name__ == '__main__' : import doctest doctest.testmod() jauges_perso_1 = [50, 60, 80] print(jauges_perso_1) disponible = diminuer_une_jauge(jauges_perso_1, 40, 1) if disponible == False : print("Personnage indisponible pour le moment") else : print("Personnage ok pour le moment.") print(jauges_perso_1)

Attention pendant la rédaction de vos propres tests : il faut que le rendu soit exactelement celui de la console. Pas d'espace en plus ou en moins.

Ainsi, cette réponse fonctionne : [0, 2, 10]
Alors que celle-ci non : [0,2,10]

Si vous oubliez que la console répond en plaçant un espace après chaque virgule, votre test risque d'échouer "pour rien".

N'oubliez pas non plus de laisser une ligne vide après le dernier test (ligne 33 de la correction).

✎ 15° Créer une fonction-procédure multiplication qui multiplie par effet de bord les éléments du tableau transmis par le second paramètre coef.

Prototype de la fonction : multiplication(tableau, coef).

Exemple d'utilisation :

>>> valeurs = [1, 2, 3, 4] >>> multiplication(valeurs, 10) >>> valeurs [10, 20, 30, 40]

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 (méthode classique)

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é des tuples EN PYTHON

En Python, les tuples sont non mutables : 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 plus d'une donnée par une fonction, typiquement ce qu'on appelle un enregistrement de données
  • Volonté de transmettre une donnée non mutable

Voici un programme qui possède une fiche d'enregistrement sur un produit : son nom, le nombre vendu et la marge sur chaque vente.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
fiche_produit_1 = ('Jeu vidéo de la mort qui tue', 103, 20.3) 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) ''' return ('vide', 0) if __name__ == '__main__' : import doctest doctest.testmod() fiche_marge = fournir_fiche_marge(fiche_produit_1)

16° Lors de l'appel de la ligne 18, 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.

17° Modifier la fonction pour qu'elle fasse le travail qu'on lui demande de faire.

...CORRECTION...

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
fiche_produit_1 = ('Jeu vidéo de la mort qui tue', 103, 20.3) 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_marge = fournir_fiche_marge(fiche_produit_1)

18° Que va afficher le programme si on rajoute la ligne 21 suivante  :?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
fiche_produit_1 = ('Jeu vidéo de la mort qui tue', 103, 20.3) 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_marge = fournir_fiche_marge(fiche_produit_1) print(fiche_marge[1])

19° 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 venir 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.

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

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
fiche_produit_1 = ('Jeu vidéo de la mort qui tue', 103, 20.3) 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() (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 envoie d'un tuple visible avec ceci

(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)

21° 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.