L’objectif du TP est de présenter les éléments de syntaxe à connaître obligatoirement sur les chaînes de caractères et les listes, puis de le mettre en application sur quelques exemples.
Cette section donne les différents éléments du langage python dont la connaissance est exigible car explicitement au programme d'informatique. Vous devez les connaître par cœur.
Une chaîne de caractères peut être écrite entre guillemets simples, doubles, ou triples. Les quatre instructions suivantes correspondent à la même chaîne de caractères.
'bonjour'
'bonjour'
"bonjour"
'bonjour'
'''bonjour'''
'bonjour'
"""bonjour"""
'bonjour'
'' # Cas particulier : la chaîne vide
''
L'utilisation des différents types de guillemets permet de créer des chaînes de caractères contenant des guillemets :
"aujourd'hui"
"aujourd'hui"
'je cite "du texte"'
'je cite "du texte"'
On peut concaténer des chaînes de caractères avec l'opérateur
+
et répéter des chaînes de caractères avec l'opérateur *
.
'bon'+'jour'
'bonjour'
2*'bon'
'bonbon'
La fonction len()
renvoie la longueur d'une chaîne :
len('abcdefghijklmnopqrstuvwxyz')
26
On peut accéder aux éléments d'une chaîne de caractères par leurs indices, le premier caractère a pour indice 0.
mot = 'Python'
mot[0]
'P'
mot[1]
'y'
mot[5] # sixième lettre du mot
'n'
len(mot)
6
On peut utiliser des indices négatifs pour compter en partant de la droite, le dernier caractère de la chaîne a pour indice $-1$.
mot[-1]
'n'
mot[-2]
'o'
On peut extraire des tranches d'une chaîne de caractères avec la syntaxe suivante (on parle de slicing) :
mot[0:2] # Les caractères de l'indice 0 inclus à l'indice 2 exclu
'Py'
mot[2:5] # Les caractères de l'indice 2 inclus à l'indice 5 exclu
'tho'
Les valeurs par défaut du premier et du deuxième indice valent respectivement 0 et la longueur de la chaîne de caractères (cet indice étant exclu):
mot[:2] # Les caractères de l'indice 0 inclus à l'indice 2 exclu
'Py'
mot[2:] # Les caractères de l'indice 2 inclus à la fin de la chaîne
'thon'
On peut aussi utiliser un troisième indice, qui correspond à un pas d'itération :
alphabet = 'abcdefghijklmnopqrstuvwxyz'
alphabet[0:15:2] # Les caractères de l'indice 0 inclus à l'indice 15 exclu, de 2 en 2.
'acegikmo'
alphabet[0:15:3] # Les caractères de l'indice 0 inclus à l'indice 15 exclu, de 3 en 3.
'adgjm'
On peut itérer sur les caractères d'une chaîne de caractères de deux
manières. Soit avec les indices (premier code ci-dessous), soit avec une
syntaxe plus légère (second code ci-dessous). Les deux codes font la même
chose : ils affichent successivement tous les caractères de la chaîne de
caractères chaine
.
On itère avec les indices:
chaine = 'bonjour'
for i in range(len(chaine)):
caractere = chaine[i]
print(caractere)
On itère directement sur les caractères:
chaine = 'bonjour'
for caractere in chaine:
print(caractere)
La syntaxe plus légère a l'inconvénient de ne pas mettre en évidence l'indice des caractères, qui est parfois utile.
Q1. Écrivez une fonction voyelles(s)
prenant en argument une
chaîne de caractères s
et renvoyant le nombre de voyelles
dans cette chaîne de caractères. (Pour déterminer si un
caractère est une voyelle, on peut utiliser des expressions
booléennes comme caractere == 'a'
ou bien
caractere in 'aeiouy'
.)
Les appels
voyelles('astrophysique')
,
voyelles('abracadabra')
et
voyelles('grrr')
doivent respectivement renvoyer 6
,
5
et 0
.
Q2. Écrivez une fonction inverse_chaine(s)
prenant en argument une
chaîne de caractères s
et renvoyant la même chaîne dans l'ordre inverse.
Par exemple inverse_chaine('retartiner')
doit renvoyer
'renitrater'
.
Comme pour les chaînes de caractères, cette section donne les différents éléments du langage python dont la connaissance est exigible : vous devez les connaître par cœur.
Une liste est une collection d'objets python. On peut les créer en les écrivant explicitement. Remarquez qu'on peut mélanger différents types (entiers, flottants, chaînes de caractères, etc.) dans une liste.
[2, 4, 6, 8]
[2, 4, 6, 8]
[2, 4, 'bonjour']
[2, 4, 'bonjour']
On peut aussi créer des listes par compréhension :
[2*x for x in range(1, 5)]
[2, 4, 6, 8]
Comme pour les chaînes de caractères, on peut concaténer des
chaînes de caractères avec l'opérateur +
et répéter des
chaînes de caractères avec l'opérateur *
.
Remarquez que la répétition peut être utile pour créer une liste remplie de zéros.
[1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
[0]*10
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Les listes sont ce qu'on appelle des types muables: on peut
modifier leur contenu. Par exemple en leur ajoutant un élément avec la
méthode append
:
L = [1, 2, 3]
L.append(4)
L
[1, 2, 3, 4]
La méthode append
peut être utilisée pour initialiser des listes à
partir d'une liste vide. Le code ci-dessous :
L = [] # Liste vide
for i in range(10):
L.append(i) # On ajoute les entiers strictement inférieurs à 10.
print(L)
affiche [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
.
Il faut préférer l'utilisation de append par rapport à
l'opérateur +
lorsque c'est possible. En effet, pour ajouter un
élément à une liste, on peut envisager deux syntaxes :
L = [1, 2, 3]
L.append(4) # Avec append
L
[1, 2, 3, 4]
L = L + [5] # Avec +
L
[1, 2, 3, 4, 5]
L'utilisation de +
est moins efficace, car la ligne
L = L + [5]
est interprétée de la manière suivante :
L + [5]
L
à laquelle on a ajouté un élémentL
: la nouvelle
liste écrase l'ancienne.Ces opérations ont demandé de créer une copie de la liste L
en
mémoire, alors que append
ajoute un élément à une liste sans en
faire de copie : append
est plus efficace.
Remarque : append
n'est pas définie pour les chaînes de
caractères.
La fonction len()
renvoie la longueur d'une liste :
len([1, 2, 3, 4])
4
On peut accéder aux éléments d'une liste de caractères par leurs indices, exactement comme pour les chaînes de caractères, la technique du slicing est la même :
L = [2, 4, 6, 8, 10]
L[0]
2
L[2]
6
L[-1]
10
L[1:3]
[4, 6]
L[:2]
[2, 4]
L[::3]
[2, 8]
On peut modifier les éléments d'une liste :
L = [1, 2, 4, 5]
L[1]
2
L
[1, 2, 4, 5]
On remarque ici que les listes sont muables : on peut modifier
leur contenu, par opposition aux chaînes de caractères qui sont
immuables. La commande ci-dessous affiche un message d'erreur et s
n'est pas modifiée :
s = 'abcd'
s[0] = 'A'
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[53], line 1 ----> 1 s[0] = 'A' TypeError: 'str' object does not support item assignment
Si on veut changer le contenu d'une chaîne de caractères, il faut en créer une nouvelle, par exemple de cette manière :
s1 = 'abcd'
s2 = 'A' + s[1:]
s1
'abcd'
s2
'Abcd'
La méthode pop()
supprime le dernier élément d'une liste et le
renvoie en valeur de retour :
L = [1, 2, 3, 4]
a = L.pop()
L
[1, 2, 3]
a
4
Cette méthode nous servira principalement à implémenter une structure de
données appelée pile plus tard dans l'année.
Elle n'est pas
particulièrement utile ici.
Il faut préférer l'utilisation de pop par rapport au slicing. En effet, pour supprimer le dernier élément d'une liste, on peut envisager deux syntaxes :
L = [1, 2, 3, 4]
L.pop() # Avec pop
4
L
[1, 2, 3]
L = L[:-1] # Avec du slicing
L
[1, 2]
L'utilisation du slicing est moins efficace, car la ligne
L = L[:-1]
est interprétée de la manière suivante :
L[:-1]
,L
à laquelle on a retiré un élément,L
: la nouvelle
liste écrase l'ancienne.Ces opérations ont demandé de créer une copie de la liste L
en
mémoire, alors que pop
supprime le dernier élément d'une liste sans
en faire de copie : pop
est plus efficace.
Remarque : pop
n'est pas définie pour les chaînes de
caractères.
On peut itérer sur les éléments d'une liste de deux
manières. Soit avec les indices (premier code ci-dessous), soit avec une
syntaxe plus légère (second code ci-dessous). Les deux codes font la même
chose : ils affichent successivement tous les éléments de la liste
L
.
On itère sur les indices:
L = [1, 2, 3, 4, 5, 6]
for i in range(len(L)):
element = L[i]
print(element)
On itère sur les valeurs:
L = [1, 2, 3, 4, 5, 6]
for element in L:
print(element)
Q3. Écrivez une fonction moyenne(L)
prenant en argument
une liste de nombres et renvoyant leur moyenne.
Vous n'avez pas le
droit d'utiliser la fonction sum
intrinsèque de python.
moyenne([1, 2, 3, 4])
doit renvoyer 2.5
.
Q4. On veut écrire une fonction maximum(L)
prenant en argument
une liste de nombres et renvoyant la valeur de leur maximum. Vous
n'avez pas le
droit d'utiliser la fonction max
intrinsèque de python. Pour cela :
[1, 2, 5, 13, 14, 9, 8, 9, 15, 4, 3, 6]
.maximum([1, 9, 2, 3, 6])
renvoie bien 9
.Q5. Écrivez une fonction indices_minimum(L)
prenant en argument
une liste de nombres et renvoyant une liste contenant les indices
i
pour lesquels L[i]
est minimum.
Par exemple,
indices_minimum([5, 2, 3])
doit renvoyer [1]
et
indices_minimum([4, -1, 2, -1])
doit renvoyer [1, 3]
.
Q6. Écrivez une fonction pairs(L)
prenant en argument une
liste L
d'entiers et retournant la liste des éléments pairs de
L
.
Par exemple pairs([1, 2, 3, 4, 2])
doit renvoyer [2, 4, 2]
.
Le second maximum d'une liste est sa deuxième plus grande valeur. Par
exemple, le second maximum de [1, 2, 14, 8, 20, 7]
est 14
.
Pour simplifier, on suppose que tous les éléments de la liste sont distincts.
Pour déterminer le second maximum d'une liste, on propose l'algorithme suivant :
Q7. Écrivez une fonction second_max(L)
renvoyant le second
maximum d'une liste en s'appuyant sur l'algorithme donné ci-dessus.
On supposera que le tableau contient au moins deux éléments.
Les chaînes de caractères en python disposent d'une méthode
split()
qui renvoie une liste des mots de la chaîne en utilisant
l'espace (' '
) comme séparateur de mot:
s = "Une phrase dans une chaîne de caractères"
s.split()
['Une', 'phrase', 'dans', 'une', 'chaîne', 'de', 'caractères']
Q8. Écrivez une fonction decoupe(s)
prenant en argument
une chaîne de caractères et renvoyant la même liste que
s.split()
(sans utiliser s.split()
évidemment !).
Q9. Écrivez un programme qui établit la liste de tous les nombres premiers compris entre 1 et 1000 en utilisant la méthode du crible d'Ératosthène :
La suite de Collatz du nombre entier N est définie comme suit:
Par exemple, pour $N=13$, on obtient la suite: 13, 40, 20, 10, 5, 16, 8, 4, 2,1.
On conjecture que toutes les suites ainsi définies finissent par 1.
Q10. Écrivez une fonction collatz(N)
qui prend en argument
un entier N
et qui retourne une liste L
contenant tous les éléments de la suite.
Par exemple collatz(13)
retournera
[13,40,20,10,5,16,8,4,2,1]
.
On peut tracer l'allure de cette suite à l'aide des commandes suivantes :
import matplotlib.pyplot as plt
plt.figure() # Initialise une nouvelle figure
plt.plot(collatz(13))
plt.show()
Q11. Écrivez une fonction plus_longue(M)
qui prend en argument
un nombre entier M
et qui renvoie l'entier $N < M+1$ dont la suite de Collatz est la plus longue.
Par exemple plus_longue(4)
renverra le nombre 3
.
Q12. En vous inspirant du code ci-dessus, tracez l'allure de la plus longue suite telle que $N< 1000$.
La suite de Conway est une suite dont le premier terme est 1 et dans
laquelle on trouve un terme en énonçant les chiffres qui
composent le terme précédent. Les premiers termes sont donc :
1
11
21
1211
111221
312211
etc.
Q13. Écrivez une fonction affiche_conway(n)
qui retourne les
n
premiers termes de la suite de Conway.
Par exemple affiche_conway(4)
doit afficher
1
11
21
1211
Q14 Définissez la liste semaine
contenant sept chaînes de
caractères correspondant aux jours de la semaine
('lundi'
, 'mardi'
, etc.)
puis posez week = semaine
.
Remplacez le premier terme
de week
par 'monday'
.
Que sont devenues les deux listes semaine
et
week
?
L'affectation en Python est l'association entre un nom de variable et une valeur. Lorsqu'on affecte une variable à une autre variable, on crée simplement un autre nom qui partage la même valeur en mémoire.
Cela ne pose pas de problème avec les types int
, float
,
bool
et str
car les valeurs elle-mêmes ne sont pas
modifiables (en Python en dit que ces types int
,
float
, bool
, str
sont immuables, pour changer la valeur associée à la variable il faut réaliser une nouvelle
affectation).
De la même façon, l'affectation d'une variable à une autre variable
d'une valeur de type list
, ne
crée pas une nouvelle liste qui soit une copie de la première, mais met simplement en place un
nouveau nom qui référence la même liste en mémoire. Or il est possible de modifier directement
cette valeur liste en utilisant les opérateurs et méthodes vus précédemment. Si deux variables référencent la même liste, les mo`difications réalisées en utilisant une variable seront visibles aussi avec
l'autre variable.
On peut vérifier tout cela en utilisant la fonction id()
, qui
donne l'\og identité \fg\ d'un objet python, c'est-à-dire son adresse en
mémoire donnée sous la forme d'un entier.
Q15. Vérifiez que id(semaine)
et id(week)
renvoient bien la même adresse.
Pour créer une copie d'une liste en étant sûr que les modifications ne toucheront pas la liste originale, il faut utiliser une des méthodes suivantes :
liste2 = [x for x in liste1]
for
:liste2 = []
for x in liste1:
liste2.append(x)
liste2 = liste1[:]
copy
: liste2 = liste1.copy()
Q16. Testez ces instructions en réalisant quatre copies de la liste
semaine
, nommées week1
, week2
, week3
et week4
, et en vérifiant
qu'on peut modifier les éléments de ces copies sans modifier la liste
originale. Vérifiez que les identifiants de ces quatre listes sont bien
différents entre eux, et différents de l'identifiant de semaine
.