types construits

Cette page aborde les notions avancées sur les Listes. Il est nécessaire de consulter auparavant la page sur les Listes: les notions de base.

On pourra également revenir sur la page 1 : variables natives de base

Après la lecture, on traitera le TP sur les variables utilisant Pythontutor.

Les structures de données et les types construits

Les structures de données définissent la manière avec laquelle sont stockées les données dans un langage.

Les types construits, comme les listes et les dictionnaires sont contruits à partir des types de bases que l’on a déjà vus. Ce sont d’autres moyens d’organiser et d’agencer les types de base dans d’autres structures.

Types séquentiels : les listes et les tuples

Une séquence est une structure de données qui stocke une collection d’éléments dans un ordre déterminé.

Listes

Definition: Une liste est une collection ordonnée d’objets. Au niveau de la mémoire de l’odinateur, une liste porte un nom, et fait référence à des espaces mémoire pour chaque élément de liste. Ces éléments (espaces mémoires) font eux-même reference aux emplacement mémoire qui stockent les valeurs ou objets.

En python: Une liste est entourée de crochets [ ]

Les éléments contenus peuvent être de tout type.

On accède à un élément d’une liste grace à sa position, appelée indice. Le premier élément a pour indice zero.

La liste `voyelles` est une collection contenant les caractères

La liste `voyelles` est une collection contenant les caractères

Un indice négatif donne accès à la liste à partir du dernier élément.

voyelles = ['e','i','o']
voyelles[0]
# affiche e
voyelles[-1]
# affiche o
voyelles
# affiche ['e','i','o']

Les listes sont mutables : On peut modifier un seul de ses éléments à partir de son indice :

voyelles[2] = 'y'
voyelles
# affiche ['e','i','y']

Ceci n’est pas possible avec le type natif str, qui, lui est un type non mutable.

Construire une liste avec une boucle

Les boucles while etfor permettent d’itérer sur les éléments d’une séquence: (testez le dans l'editeur Python)

# Boucle while
squares = []
i = 0
while i <= 100:
  squares.append (i ** 2)
  i += 1

# Boucle for
squares = []
for i in range (101) :
  squares.append (i ** 2)

Construire une liste par compréhension

Pour construire une liste par compréhension, on place une boucle bornée à l’INTERIEUR les crochets. Cela créé un éléments dans la matrice pour chaque valeur de l’itérable

# Définition par compréhension
squares = [i ** 2 for i in range (10) ]
squares
# affiche [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

On peut combiner les expressions entre les crochets, en ajoutant par exemple une condition. Ainsi, si l’on veut uniquement le carré des nombres pairs (if i % 2 == 0):

# carre des nombres pairs
squares = [i ** 2 for i in range (101) if i % 2 == 0]

Pour un tableau, on peut créer une liste par compréhension à l’intérieur de la première liste:

M = [[0 for j in range(3)] for i in range(3)]
M
# affiche [[0, 0, 0], [0, 0, 0], [0, 0, 0]]

Tuples

Un tuple est entouré de parenthèses ( )

On accède à l’un des éléments à l’aide de son indice, comme pour les listes.

Par contre, le tuple est non mutable : on ne peut pas en modifier l’un de ses éléments. Il faut refaire, au besoin, une affectation complète de tout le tuple.

elementaire = ('CP','CE1','CE2')
elementaire[1]
# affiche CE1
elementaire[2] = 'CM2'
# affiche TypeError
elementaire = ('CP','CE1','CM2')
elementaire
# affiche ('CP','CE1','CM2')

Mappages : les dictionnaires

Un mappage est une structure de données qui relie 2 informations ou plus, appelées paires clé : valeur. En python, cette structure est le dictionnaire.

Un dictionnaire est entouré d'accolades { }. Les paires sont séparées par une virgule.

Par exemple, pour créer un dictionnaire non vide, on peut faire :

capitales = {'France':'Paris','Italie':'Rome','Allemagne':'Berlin'}

Mais on peut aussi ajouter chaque paire en faisant :

capitales = {} # dictionnaire vide
capitales['France'] = 'Paris'
capitales
# affiche {'France': 'Paris'}

Pour accéder à une valeur, on utilise la clé comme index: capitales['France'] = 'Paris'

Pour accéder aux clés d’un dictionnaire: on utilisera les méthodes keys avec par exemple capitales.keys()

Pour accéder aux valeurs: on utilise la méthode value, avec par exemple capitales.values()

Pour accéder aux paires clé-valeurs: méthode items, avec par exemple capitales.items()

méthodes de listes

Les listes sont présentées à la page variables

Pour commencer, rappelons comment retrouver la liste des méthodes définies sur le type list :

help(list)

append

append(element) ajoute un élément en fin de liste

aeroports = ['CDG','ORY','LIS']
aeroports.append('NY')
aeroports
# affiche ['CDG','ORY','LIS','NY']

pop

pop() supprime le dernier élément et renvoie sa valeur.

aeroports = ['CDG','ORY','LIS','NY']
aeroports.pop()
# affiche 'NY'
aeroports
# affiche ['CDG','ORY','LIS']

index

index(element) retourne la position (index) de cet élément dans la liste (ou du moins la première occurence s’il y en a plusieurs).

aeroports = ['CDG','ORY','LIS','NY']
aeroports.index('ORY')
# retourne 1

insert

insert(index, element) insère l’élément à l’index précisé.

aeroports = ['CDG','ORY','LIS','NY']
aeroports.insert(2,'LCY')
# la liste aeroport est alors
# ['CDG','ORY', 'LCY', LIS','NY']

remove et del

remove(element) supprime un élément d’une liste. Si l’élément apparait plusieurs fois dans la liste, seule la premiere occurence est supprimée.

del liste[indice] supprime l’élément de la liste à partir de son indice.

aeroports = ['CDG','ORY','LIS','NY']
aeroports.remove('LIS')
aeroports
# affiche ['CDG','ORY','NY']
del aeroports[0]
aeroports
# affiche ['ORY','NY']

découpe d’une liste

une découpe est une partie de liste, spécifiée à partir des indices :

etats = ['CH','GB','NL','PL','RO','SK']
etats[2:4]
# affiche ['NL','PL']
etats[:2] # sans specifier le premier indice
# affiche ['CH','GB'] # commence au debut
etats[3:] # sans specifier l'indice de fin
# affiche ['PL','RO','SK'] # jusqu'à la fin

copie d’une liste

Une copie d’une liste permet d’utiliser le contenu de la liste copiée sans affecter la liste d’origine (voir TP sur les variables). C’est une copie par valeurs.

Pour copier une liste, on peut :

  • la découper sans mentionner les 2 indices:
etats = ['CH','GB','NL','PL']
mes_etats = etats[:] # liste copiée par valeur dans mes_etats
  • ou bien utiliser la fonction list:
etats = ['CH','GB','NL','PL']
mes_etats = etats[:] # liste copiée par valeur dans mes_etats
mes_etats = list(etats)

On peut alors vérifier qu’il s’agit maintenant d’une copie par valeurs :

mes_etats.append('DK')
mes_etats
# affiche ['CH','GB','NL','PL','DK']
etats
# affiche ['CH','GB','NL','PL']

Sans cette astuce, la copie se ferait par référence (rappelez-vous: Liste = mutable)

Trier une liste

Il y a 2 fonctions de tri :

  • La fonction sorted renvoie une copie de la liste triée dans l’ordre naturel (alphanumerique) sans modifier la liste d’origine.
L = [9, 5, 1, 3, 4]
sorted(L)
# affiche [1, 3, 4, 5, 9]

Puis:

L
# affiche [9, 5, 1, 3, 4]
  • La méthode sort permet de trier la liste en place.
L = [9, 5, 1, 3, 4]
L.sort()
# L est transformee en
# [1, 3, 4, 5, 9]

Choix d’un élément aléatoire dans une liste.

Il faut importer la fonction choice de la librairie random:

from random import choice
L = [1, 10, 100, 1000]
print(choice(L))

Affiche un élément au hasard: 1, 10, 100 ou 1000.

méthodes de dictionnaires

Les dictionnaires sont présentés à la page sur les variables

keys

méthode qui permet d’accéder aux clés d’un dictionnaire (retourne une liste de clés) :

capitales = {'France':'Paris','Italie':'Rome','Allemagne':'Berlin'}
capitales.keys()
# affiche dict_keys(['France', 'Italie', 'Allemagne'])

values

méthode pour accéder aux valeurs d’un dictionnaire (retourne une liste de valeurs):

capitales = {'France':'Paris','Italie':'Rome','Allemagne':'Berlin'}
capitales.values()
# affiche dict_values(['Paris', 'Rome', 'Berlin'])

items

méthode pour accéder aux paires clé-valeurs d’un dictionnaire (retourne une liste de tuples):

capitales = {'France':'Paris','Italie':'Rome','Allemagne':'Berlin'}
capitales.items()
# affiche dict_items([('France', 'Paris'), ('Italie', 'Rome'), ('Allemagne', 'Berlin')])

copier un dictionnaire

On peut utiliser la fonction dict pour faire une copie par valeur d’un dictionnaire :

mes_capitales = dict(capitales)

Sans cette astuce, la copie se ferait par référence (Dictionnaire = mutable)

Dataframes

Un Dataframe est un objet qui permet de mieux représenter et travailler sur les tables. C’est un outil puissant, qui necessite un apprentissage supplémentaire, comme une extension du langage python. Voir ici : towardsdatascience.com

Objets mutables et non mutables

En Python, il existe deux types d’objets: les mutables (listes, dictionnaires, sets, objets customisés, etc) et les non mutables (string, int, float, tuple, etc).

Les mutables sont ceux qu’on peut modifier après leur création. Les non mutables sont ceux qu’on ne peut pas modifier après création.

Lorsque 2 références pointent sur le même objet, ce qui est possible avec les mutables, il faut s’attendre à ce que la modification de l’un entraine celle de l’autre (effet de bord).

C’est le mot-clé IS qui va permettre de tester si 2 noms pointent vers la même réference en mémoire:

x = ["apple", "banana", "cherry"]
y = ["apple", "banana", "cherry"]
x == y
# affiche True
x is y
# affiche False

Pour plus de précisions sur ces différences, voir le TP utilisant Pythontutor

Portée des variables

Un effet de bord est une modification d’une variable qui affecte l’état du programme en dehors de la fonction où elle a lieu. Cela peut arriver avec des variables globales, déclarées en dehors de toute fonction.

Pour une variable x non mutable, déclarée dans le corps du programme, celle-ci peut être lue dans une fonction où elle n’a pas été definie. Par contre, pour la modifier dans cette fonction, il faudra la déclarer avec global x dans cette fonction.

Suite

TP utilisant Pythontutor