Algo & Prog 1 Python : CM séance 02
2. Structures de données
2.1. Tuples
On a vu les types simples de Python : int
, float
, bool
, str
Il y a de nombreux autres types et opérations associées.
Un tuple = plusieurs valeurs séparées par une virgule
>>> a = 7, 4, "oui" # (7, 4, "oui")
on peut mettre autour des parenthèses :
>>> a = (7, 4, "oui") # (7, 4, "oui")
>>> type(a) # <class 'tuple'>
>>> type(a) == tuple # True
Comment récupérer les valeurs ?
>>> x, y, z = a
>>> x # 7
>>> y # 4
>>> z # "oui"
Si on se trompe ?
>>> x, y = a # ValueError: too many values to unpack (expected 2)
>>> x, y, z, t = a # ValueError: need more than 3 values to unpack
Utilité :
-
Échanger 2 variables x et y
en C :tmp = x ; x = y ; y = tmp;
en python :x, y = y, x
-
Une fonction peut renvoyer plusieurs valeurs :
def saisir_nom_prenom_age () : nom = input("Nom = ") prenom = input("Prénom = ") age = int(input("Age = ")) return nom, prenom, age n, p, a = saisir_nom_prenom_age()
Opérations sur un tuple :
-
concaténation
>>> a = 7, 4, "oui" >>> b = True, 3.14 >>> c = 5, >>> a+b # (7, 4, 'oui', True, 3.14) >>> a+c # (7, 4, 'oui', 5)
-
longueur
>>> len(b) # 2
-
transtypage
>>> tuple("salut") # ('s', 'a', 'l', 'u', 't')
-
on peut aussi utiliser des indices, voir plus loin
2.2. Boucle for et range
Boucle for
très différente du C :
for variable1 in expression1 :
bloc1
expression1
est de n'importe quel type itérable ;
variable1
prend successivement les valeurs de chaque élément de expression1
.
Exemples :
-
avec des tuples
for i in 7, 4, "oui" : print(i)
-
avec des strings
for c in "plop" : print(c)
-
avec une fonction qui renvoie un itérable :
def quelques_entiers() : return 5, 7, 11 for i in quelques_entiers() : print(i)
Comment faire une boucle sur un intervalle, comme en C ? Avec la classe range
for i in range(1,10) :
print(i) # de 1 à 10-1
On peut changer l'incrément :
for i in range(1,10,3) :
print(i) # 1 4 7
Usage :
- boucler de
0
àb
exclus dans le sens croissant :range (b)
- boucler de
a
àb
inclus dans le sens croissant :range (a, b+1)
- boucler de
b
àa
inclus dans le sens décroissant :range (b, a-1, -1)
Opérations supplémentaires sur un range
>>> a = range(5)
>>> type(a) # <class 'range'>
>>> type(a) == range # True
>>> tuple(a) # (0, 1, 2, 3, 4)
>>> len(a) # 5
2.3. Les listes
Une liste de valeurs entre crochets, éventuellement de types différents
>>> a = [7, 4, "oui"]
>>> type(a) # <class 'list'>
>>> type(a) == list # True
Accès au valeurs :
>>> a[0] # 7
>>> a[3] # IndexError : sortie de tableau
>>> a[-1] # "oui" : dernier élément
Modification :
>>> a[1] = 3.14
>>> a # [7, 3.14, 'oui']
>>> a[3] = 5 # IndexError
Opérations :
-
longueur
>>> len(a) # 3
-
liste vide
>>> len([]) # 0
-
concaténation
>>> b = a + ['plop'] # [7, 4, 'oui', 'plop'] on crée b
-
apposition (append)
>>> a += [123, 45] # [7, 3.14, 'oui', 123, 45] on modifie a >>> a.append(11) # [7, 3.14, 'oui', 123, 45, 11]
Voir aussi : >>> help(list)
Itération :
for elt in a :
print(elt)
Itérer en récupérant l'indice :
for i,elt in enumerate(a) :
print(i,elt)
Transtypage :
>>> a = [7, 4, "oui"]
À la main :
def transformer_liste_en_tuple(maliste) :
montuple = ()
for elt in maliste :
montuple += (elt,)
return montuple
>>> transformer_liste_en_tuple(a) # (7, 4, 'oui')
def transformer_tuple_en_liste(montuple) :
maliste = []
for elt in montuple :
maliste += [elt]
return maliste
>>> b # (5, 7, 'oui')
>>> transformer_tuple_en_liste(b) # [5, 7, 'oui']
>>> b = tuple(a) # (7, 4, 'oui')
>>> c = list(b) # [7, 4, 'oui']
>>> a == c # True (même longueur et valeurs)
Une fonction peut évidemment recevoir en paramètre une liste et renvoyer une liste. Exemple
def extraire_entiers_pairs (liste_entiers) :
res = []
for entier in liste_entiers :
if entier % 2 == 0 :
res += [entier]
return res
>>> extraire_entiers_pairs ([5, 6, 8, 11]) # [6, 8]
Marche aussi sur les tuples, ou n'importe quel itérable :
>>> extraire_entiers_pairs ((5, 6, 8, 11)) # [6, 8]
>>> extraire_entiers_pairs (range(5)) # [0, 2, 4]
Appartenance : in
>>> 4 in [7, 4, 'oui'] # True
>>> 4 in (7, 4, 'oui') # True
>>> 4 in range(5) # True
>>> 'lo' in 'plop' # True
>>> [7,4] in [7, 4, "oui"] # False : ne marche pas pour les sous-listes
>>> [5,7] in [[5,7],11] # True
Obtenir l'indice :
>>> a.index(4) # 1
>>> a.index(5) # ValueError: 5 is not in list
Il faut tester d'abord avec in
:
>>> valeur = 5
>>> if valeur in a :
print(a.index(valeur))
>>> valeur = 4
>>> if valeur in a :
print(a.index(valeur))
Bilan : différence entre tuples et les listes ?
-
On peut accéder aux tuples via un indice :
>>> a = (5,7,11) >>> a[1] # 7
-
On peut également éclater une liste :
>>> b = [12, 15] >>> x,y = b # x = 12 et y = 15
En fait, la différence est dans l'immuabilité.
2.4. Types immuables
Certains types sont immuables (uk : immutable) = on ne peut pas modifier une valeur.
Les types simples sont immuables :
-
int
,float
,bool
,complex
,NoneType
: les valeurs sont des constantes -
les
str
sont aussi immuables : on ne peut pas changer une lettre>>> s = "plop" >>> s[2] # 'o' >>> s[2] = 'i' # TypeError: 'str' object does not support item assignment
-
les tuples sont immuables :
>>> a = (5,7,11) >>> a[1] = 13 # TypeError: tuple does not support item assignment
À l'inverse, les listes, dictionnaires et ensembles sont muables.
Intérêts :
- une fonction ne peut pas modifier une variable immuable passée en paramètre (bien que passée par référence) ;
- les types immuables sont hashables = peuvent servir de clé dans un dictionnaire (vu après).
- Important :
-
Comme les variables sont des références, et que les listes sont muables, on a ceci :
>>> b = [7, 3] >>> c = b # c et b désignent la même liste >>> b.append(5) # on modifie b >>> c [7, 3, 5] # on a donc aussi modifié c
De la même façon :
>>> def f(l) : # passage de paramètre par référence l[0] = 9 # on modifie l >>> f(b) >>> b [9, 3, 5] # la fonction a bien agi sur b
2.5. Dictionnaires
Un dictionnaire est une sorte de liste, qui associe des mots clés à des valeurs.
type : dict
syntaxe : { "mot clé" : valeur, ...}
dictionnaire vide : {}
Exemple : ingrédients de la pâte brisée
pate = { "farine" : "200g",
"beurre" : "100g",
"eau" : "1 verre",
"sel" : "1 pincée" }
>>> pate
>>> type(pate) # <class 'dict'>
>>> type(pate) == dict # True
Retrouver une valeur
>>> pate["beurre"] # '100g'
Gestion des erreurs
>>> pate["levure"] # KeyError: 'levure'
On peut aussi utiliser get
, ce qui évitera une erreur si non trouvé
>>> pate.get("beurre") # '100g'
>>> pate.get("levure") # None
Avec get
on peut donner une valeur par défaut :
>>> pate.get("beurre", "pas prévu") # '100g'
>>> pate.get("levure", "pas prévu") # 'pas prévu'
On peut rajouter des clés ou modifier des valeurs :
>>> pate["farine"] = "250g"
>>> pate["sucre"] = "3 cuillerées"
>>> pate # {'sucre': '3 cuillerées', 'eau': '1 verre', 'beurre': '100g',
# 'farine': '250g', 'sel': '1 pincée'}
L'ordre d'insertion est garanti depuis python 3.7, voir https://docs.python.org/3/whatsnew/3.7.html
On peut aussi concaténer avec un autre dictionnaire :
>>> pate.update( {"beurre" : "125g",
"jaune d'œuf" : 1,
"cannelle" : "1 cuillerée"} )
>>> pate # {'cannelle': '1 cuillerée', 'beurre': '125g', "jaune d'œuf": 1,
# 'farine': '400g', 'sel': '1 pincée', 'eau': '1 verre'}
Si vous n'aimez pas la cannelle on peut la supprimer
>>> del pate["cannelle"]
>>> pate # {'beurre': '125g', "jaune d'œuf": 1,
# 'farine': '400g', 'sel': '1 pincée', 'eau': '1 verre'}
Au fait combien faut-il d'ingrédients ? Demander la taille du dictionnaire :
>>> len(pate) # 5
Test d'appartenance : clé in
dictionnaire
>>> "farine" in pate # True
>>> "bierre" in pate # False
Je voudrais maintenant itérer sur les ingrédients, i.e. sur les clés :
>>> for ingredient in pate :
print(ingredient, pate[ingredient])
(pour python >= 3.7 on peut également constater ici que l'ordre d'insertion est préservé).
Variante : on récupère directement un tuple clé,valeur :
>>> for ingredient, quantite in pate.items() :
print(ingredient, quantite)
C'est plus efficace.
On peut encore transformer les types :
>>> list(pate) # ['beurre', "jaune d'œuf", 'farine', 'sel', 'eau']
>>> tuple(pate) # ('beurre', "jaune d'œuf", 'farine', 'sel', 'eau')
>>> pate.keys() # dict_keys(['beurre', "jaune d'œuf", 'farine', 'sel', 'eau'])
>>> pate.values() # dict_values(['125g', 1, '400g', '1 pincée', '1 verre'])
>>> list(pate.values()) # ['125g', 1, '400g', '1 pincée', '1 verre']
Usage plus général :
-
on peut mettre autre chose que des strings en clé :
>>> pipo = { 83 : "Var", 3.14 : "pi", True : "noir", (1,2,3) : "soleil" } >>> pipo[83] # 'Var' >>> pipo[3.14] # 'pi' >>> pipo[True] # 'noir' >>> pipo[(1,2,3)] # 'soleil'
On ne peut mettre que des types immuables (car ils sont hashables)
→ desint
,floal
,bool
,None
,tuple
etstr
; paslist
nidict
. -
on peut mettre n'importe quel type en valeur :
>>> foot = { "champions" : (1998, 2018), "pays" : { 1986 : "Mexique", 1998 : "France", 2018 : "Russie" }, 10 : ["Platini", "Zidane", "Mbappé"], } >>> foot["champions"] # (1998, 2018) >>> foot["pays"] # {1986: 'Mexique', 2018: 'Russie', 1998: 'France'} >>> foot["pays"][1998] # 'France' >>> foot["10"] # KeyError: '10' >>> foot[10] # ['Platini', 'Zidane', 'Mbappé'] >>> foot[10][1] # 'Zidane'
Conclusion :
- outil très puissant, permet de structurer les informations ;
- par prudence : utiliser un seul type pour les clés, et un seul pour les valeurs.
2.6. Ensembles
Un ensemble est une collection de valeurs uniques.
Syntaxe :
>>> s = set()
>>> s.add(5)
>>> s.add(7)
>>> s.add(5)
>>> s # { 5, 7}
>>> type(s) # <class 'set'>
>>> type(s) == set # True
>>> t = {5, 7}
>>> s == t # True
Pour rendre uniques une liste de valeurs il suffit de la convertir en set
:
>>> l = []
>>> for i in range(10) :
l.append(i*i % 7)
>>> l
[0, 1, 4, 2, 2, 4, 1, 0, 1, 4]
>>> s = set(l)
>>> s
{0, 1, 2, 4}
>>> t = list(s)
>>> t
[0, 1, 2, 4]
Autre exemple :
>>> melodie = ['do','mi','sol','mi','fa','mi','do']
>>> notes = set(melodie) # {'sol', 'fa', 'do', 'mi'}
Les set
sont itérables et supportent le test d'appartenance in
:
>>> for note in notes :
print(note) # sol fa do mi
>>> 'mi' in notes # True
Suppression d'un élément :
>>> notes.discard('mi') # {'sol', 'fa', 'do'}
>>> notes.discard('ré') # sans effet
Il y a de nombreuses autres méthodes :
intersection
, union
, difference
, ...
Voir help(set)
pour approfondir.