Parcourir☘
Il faut connaître les différentes façons de parcourir un objet chaîne:
for ... in ...
for ... in enumerate(...)
for ... in range(....)
Parcourir les caractères☘
On peut parcourir les caractères d'une chaîne avec for in
:
>>> a = "Je suis une chaîne"
>>> for caractere in a:
... print(caractere)
...
J
e
s
u
i
s
u
n
e
c
h
a
î
n
e
Avec for caractere in a:
, la variable caractere
va parcourir un à un (dans l'ordre
de gauche à droite) chaque caractère de la chaîne.
La boucle:
for caractere in a:
print(caractere)
s'exécute donc ainsi:
- La variable
caractere
prend la valeur'J'
et le corps de boucle est exécuté (ici il s'agit de l'affichage de la valeur de la variablecaractere
). - Puis la variable
caractere
prend la valeur'e'
et le corps de boucle est exécuté. - ... et ainsi de suite jusqu'à épuisement des caractères de la chaîne.
Parcourir avec indice et caractère☘
>>> a = "Je suis une chaîne"
>>> for i, c in enumerate(a):
... print(i, c)
...
0 J
1 e
2
3 s
4 u
5 i
6 s
7
8 u
9 n
10 e
11
12 c
13 h
14 a
15 î
16 n
17 e
Avec for i, c in enumerate(a):
, la variable i
va parcourir un à un (dans l'ordre
croissant) les indices de la chaîne, tandis que la variable c
prendra pour valeur
le caractère de la chaîne correspondant à l'indice i
.
La boucle:
for i, c in enumerate(a):
print(i, c)
s'exécute donc ainsi:
- La variable
i
prend la valeur 0 et la variablec
prend la valeur'J'
et le corps de boucle est exécuté (ici il s'agit de l'affichage de la valeur de ces deux variables). - Puis la variable
i
prend la valeur 1 et la variablec
prend la valeur'e'
et le corps de boucle est exécuté. - ... et ainsi de suite jusqu'à épuisement des valeurs possibles pour les indices de la chaîne.
Parcourir avec les indices☘
>>> a = "Je suis une chaîne."
>>> for indice in range(len(a)):
... print(indice, a[indice])
...
0 J
1 e
2
3 s
4 u
5 i
6 s
7
8 u
9 n
10 e
11
12 c
13 h
14 a
15 î
16 n
17 e
18 .
Avec for indice in range(len(a)):
, la variable indice
va parcourir un à un (dans l'ordre
croissant) les indices de la chaîne.
La boucle:
for indice in range(len(a)):
print(indice, a[indice])
s'exécute donc ainsi:
- La variable
indice
prend la valeur 0
et le corps de boucle est exécuté (affichage de la valeur deindice
et du caractèrea[indice]
, c'est à direa[0]
qui est le caractère'J'
). - Puis la variable
indice
prend la valeur 1
et le corps de boucle est exécuté (affichage de la valeur deindice
et du caractèrea[indice]
, c'est à direa[1]
qui est le caractère'e'
). - ... et ainsi de suite jusqu'à épuisement des caractères de la chaîne.
Exercices☘
Exercice 1☘
Écrire un code possible pour le corps de la fonction suivante:
def compte_e(chaine):
"""
chaine -- chaine de caractères
renvoie le nombre de lettres e, E de la chaîne
"""
le principe
Le principe à utiliser ici est encore celui de l'accumulateur déjà utilisé (avec filtrage des caractères satisfaisant notre critère: ici être un 'e' ou un 'E').
On utilise une variable compteur
et on "visite" un par un les caractères de la chaîne.
On "accumule" des 1 (par sommation) dans compteur
à chaque visite d'un caractère e ou E,
ainsi au final compteur = 1 + 1 + 1 + ... + 1, expression
comptant autant de 1 qu'il y a de caractères e ou E dans la chaîne.
Après chaque "visite" de caractère, compteur aura pour valeur le nombre de caractères 'e' ou 'E' déjà visités (pour cela, avant toute visite, on doit bien sûr intialisé le compteur à 0).
En fin de visite des caractères, tous les caractères de la chaîne ayant été visités, la variable compteur contiendra le nombre total d'occurrences des lettres de l'ensemble {'e'; 'E'}.
ou
On aura besoin de tester si une variable caractere
désigne 'e' ou désigne 'E'.
En langage Python, on utilise or
:
if caractere == 'e' or caractere == 'E':
Attention.
Surtout ne pas écrire if caractere == 'e' or 'E':
, cela n'a aucun sens.
Le "ou" logique se place entre deux propositions qui peuvent être vraies ou fausses.
Par exemple caractere == 'e'
peut être vrai ou faux. Et caractere == 'E'
peut être vrai ou faux.
Mais écrire if caractere == 'e' or 'E':
revient à placer un "ou" entre caractere == 'e'
et 'E'
. Or 'E'
n'est pas vrai ou faux ! C'est un caractère, pas une proposition logique.
Bien entendu, on peut dans le langage courant commettre cet abus, mais le langage
Python ne comprendra pas l'omission faite et interprétera ce if caractere == 'e' or 'E':
d'une façon différente de ce qui est attendu.
Pseudo-code
fonction compte_e_E(chaine):
compteur ← 0
Pour chaque caractère de chaine:
si le caractère est un e ou un E:
on ajoute 1 au compteur
renvoyer compteur
Un code python possible
def compte_e(chaine):
"""
chaine -- chaine de caractères
renvoie le nombre de lettres e, E de la chaîne
"""
compteur = 0
for caractere in chaine:
if caractere == 'e' or caractere == 'E':
compteur += 1
return compteur
On peut vouloir mettre en évidence le fait qu'on ne fait rien si le caractère lu n'est pas 'e' ou 'E' (certains trouveront le code plus facile à lire ainsi, cela dépend de chacun, à vous de voir):
def compte_e(chaine):
"""
chaine -- chaine de caractères
renvoie le nombre de lettres e, E de la chaîne
"""
compteur = 0
for caractere in chaine:
if caractere == 'e' or caractere == 'E':
compteur += 1
else:
pass # instruction "on ne fait rien!"
return compteur
Pour compter aussi é, è, ...
On pourrait aussi vouloir compter é, è, ê dans les lettres e.
On peut alors utiliser in (plutôt que d'accumuler les or):
fichier ipynb
Note
On rappelle que l'extension .ipynb est celle des fichiers jupyter notebook.
Une version statique html de ce fichier ipynb:
déroulement
Regardons un peu en détail le déroulement sur cet essai:
def compte_e(chaine):
"""
chaine -- chaine de caractères
renvoie le nombre de lettres e, E de la chaîne
"""
compteur = 0
for caractere in chaine:
if caractere == 'e' or caractere == 'E':
compteur += 1
else:
pass # instruction "on ne fait rien!"
return compteur
a = compte_e('ether')
print(a)
On appelle la fonction (partie droite de l'affectation a = compte_e('ether')
):
compte_e('ether')
On a alors la situation suivante:
On exécute ensuite les lignes de code du corps de la fonction.
On exécute la ligne:
compteur = 0
La situation:
On arrive ensuite à la ligne:
for caractere in chaine:
On teste si caractere désigne une lettre 'e' et on incrémente compteur si c'est le cas:
if caractere == 'e' or caractere == 'E':
compteur += 1
else:
pass # instruction "on ne fait rien!"
On passe à la valeur suivante de caractere
:
Et on exécute le if: caractere ne désigne pas un 'e', on ne fait rien. Le schéma reste le même.
On passe à la valeur suivante de caractere
:
Et on exécute le if: caractere ne désigne pas un 'e', on ne fait rien. Le schéma reste le même.
On passe à la valeur suivante de caractere
:
Et on exécute le if: caractere désigne un 'e', on incrémente compteur.
On passe à la valeur suivante de caractere
:
Et on exécute le if: caractere ne désigne pas un 'e', on ne fait rien. Le schéma reste le même.
On termine la fonction avec la ligne return compteur
et on effectue la partie gauche de l'affectation
(ligne 17): on affecte ainsi l'étiquette a (de l'espace global)
à l'objet contenant la valeur 2 qui a été calculée.
Rappelons qu'à ce stade, la fonction ayant terminé ses calculs, plus aucune étiquette locale
à la fonction n'existe. En particulier l'objet chaîne de caractères, utilisé en argument pour l'appel,
n'est plus accessible puisqu'aucune étiquette ne désigne cet objet. Mais le nombre de lettres 'e' de cette
chaîne est accessible via le nom a
.
La dernière étape est l'exécution de print(a)
qui affiche à l'écran la valeur de l'objet désigné par a
.
Exercice 2☘
Écrire un code possible pour le corps de la fonction suivante:
def rang_premier_e(chaine):
"""
chaine -- chaine de caractères
renvoie l'indice de la première lettre e trouvée dans chaine.
Renvoie -1 si e n'est pas présent.
"""
Principe
On utilise une variable témoin
et on "visite" un par un les caractères de la chaîne.
Au départ, on itinialise témoin
à la valeur -1, pour signifier qu'avant toute visite de caractère, on n'a pas
trouvé la lettre 'e'.
Après chaque "visite" de caractère, on met à jour témoin
:
- si le caractère est un 'e', la variable
témoin
reçoit la valeur de l'indice de la lettre visitée, - sinon témoin reste égal à sa valeur précédente.
Le principe tel qu'on vient de le présenter n'est pas correct:
on obtiendrait ainsi l'indice du dernier caractère 'e' rencontré,
il ne faut pas modifier à nouveau témoin
si l'on rencontre à nouveau la lettre 'e'.
Comment savoir si le 'e' rencontré est le premier rencontré?
C'est simple: si témoin
ne vaut plus -1,
c'est qu'on a déjà rencontré un 'e', sinon c'est le premier.
On modifie donc le code d'une visite de caractère comme suit:
Après chaque "visite" de caractère, on met à jour témoin
:
- si le caractère est un 'e' et si
témoin
vaut -1: la variabletémoin
reçoit la valeur de l'indice de la lettre visitée, - sinon témoin reste égal à sa valeur précédente.
En fin de visite des caractères,
tous les caractères de la chaîne ayant été visités,
la variable témoin
contiendra -1 si on n'a jamais rencontré 'e' et l'indice du premier 'e' rencontré sinon.
Pseudo-code
fonction rang_premier_e(chaine):
témoin ← -1
Pour chaque caractère de chaine:
si le caractère est un 'e' et si témoin == -1:
témoin ← indice du caractère
sinon
on ne fait rien
renvoyer témoin
Un code python
Un premier code possible:
def rang_premier_e(chaine):
"""
chaine -- chaine de caractères
renvoie l'indice de la première lettre e trouvée dans chaine. Renvoie -1 si e n'est pas présent.
"""
témoin = -1
for indice, caractere in enumerate(chaine):
if caractere == 'e' and témoin == -1:
témoin = indice
else:
pass
return témoin
Stopper la boucle au premier e
On peut allèger ce code en profitant du fait que la fonction est stoppée dès le premier return
rencontré
(dès qu'on connaît l'image, on peut stopper le calcul):
def rang_premier_e(chaine):
"""
chaine -- chaine de caractères
renvoie l'indice de la première lettre e trouvée dans chaine. Renvoie -1 si e n'est pas présent.
"""
for indice, caractere in enumerate(chaine):
if caractere == 'e': return indice
return -1
Important
La ligne return -1
n'a pas besoin de else
:
si dans une fonction, on rencontre un return, on sort immédiatement de la fonction puisque
l'image a été obtenue.
Ainsi:
- Soit un e dans la boucle a été rencontré et on sort de la fonction avec
return indice
, la lignereturn -1
n'est donc jamais vue dans ce cas. - Soit aucun e n'est rencontré dans le parcours de la chaîne. On finit la boucle sans avoir
exécuté
return indice
. Et dans ce cas, on exécute la ligne qui suit, c'est à direreturn -1
.
Exercice 3☘
On appelle distance de Hamming entre deux chaînes de caractères A et B de même longueur le nombre d'indices i tels que A[i] \neq B[i].
Exemples.
- distance('ami' , 'amu') = 1
- distance('don' , 'bon') = 1
- distance('zozo' , 'bobo') = 2
Écrire une fonction python prenant en entrée deux chaînes de caractères de même longueur et renvoyant la distance de Hamming entre ces deux chaînes.
Principe
On utilise le principe de l'accumulateur:
une variable nombre_de_différences
est initialisée à 0,
puis on va accumuler dans cette variable le nombre de différences rencontrées.
On parcourt donc les indices de 0 à longueur(chaine)-1 (les deux chaînes données
en entrée ayant même longueur) et on ajoute 1 à nombre_de_différences
à chaque fois que les caractères de même indice sont différents dans les deux chaînes.
Pseudo-code
fonction distance(chaineA, chaineB):
nb_diff ← 0 # contiendra le nombre de différences
Pour indice allant de 0 à longueur(chaineA)-1:
si chaineA[indice] est différent de chaineB[indice]:
ajouter 1 à nb_diff
renvoyer nb_diff
Un code python
def hamming(chaine, chene):
"""
chaine -- type string
chene -- type string
renvoie la distance de Hamming entre chaine et chene.
"""
assert len(chaine)==len(chene), "Attention, les deux chaînes de caractères doivent être de même longueur."
difference = 0 # compteur de différences
for k in range(len(chaine)):
if chaine[k] != chene[k]:
difference = difference + 1
else:
pass # on ne fait rien lorsque les deux caractères sont les mêmes
return difference
Tests:
>>> hamming('abri', 'ubri')
1
>>> hamming('010101', '010110')
2
in☘
Le in
des boucles for
peut-être utilisé pour tester la présence ou non d'un caractère
dans une chaîne.
>>> 'a' in 'babar'
True
>>> 'a' in 'Python'
False
Exercice☘
Ecrire une fonction prenant en entrée une chaîne de caractères et renvoyant True si la chaîne contient au moins une voyelle et False si la chaîne n'en contient pas.
principe
On parcourt la chaîne: on peut arrêter dès qu'on rencontre une voyelle (en renvoyant True). Après le parcours complet de la chaîne, si on n'a pas rencontré de voyelle (c'est à dire si la valeur True n'a pas été renvoyée), on renvoie False.
fonction contient_voyelles(chaine):
Pour chaque caractère c de chaine:
si c est une voyelle:
renvoyer True
renvoyer False
Il vous reste à trouver comment traduire efficacement en Python le test
si c est une voyelle
.
un code python
def contient_voyelles(chaine):
"""
chaine: de type str
Renvoie True si chaine contient une voyelle,
renvoie False si chaine ne contient pas de voyelle.
"""
voyelles = "aeiouy"
for c in chaine:
if c in voyelles:
return True
return False
>>> contient_voyelles("babar")
True
>>> contient_voyelles("trph")
False
On peut également choisir de parcourir l'ensemble des voyelles et stopper dès que l'une d'elles est trouvée dans chaine:
def contient_voyelles(chaine):
"""
chaine: de type str
Renvoie True si chaine contient une voyelle,
renvoie False si chaine ne contient pas de voyelle.
"""
for v in "aeiouy":
if v in chaine:
return True
return False