Séance 3#

Objectifs

  • Compléments sur les listes

  • Ensembles et dictionnaires

  • Mot-clefs all et any

Déclaration de liste par compréhension#

Le langage python permet de construire des listes avec une syntaxe proche des mathématiques. Supposons que l’on souhaite créer la liste des entiers compris entre \(0\) et \(33\), qui sont des multiples de \(3\). Mathématiquement, l’ensemble des éléments de cette liste pourrait être décrit selon les deux manières suivantes :

\[ \{\, 3i \mid 0 \le i \le 11 \,\} \quad \text{ et } \quad \{\, n \in [0, 33] \mid n \equiv 0 \!\!\!\mod 3 \,\} \]

Avec python, on va pouvoir déclarer la liste de ces éléments d’une manière similaire. D’une part

L = [ 3 * i for i in range(0, 12) ]
print(L)
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33]

et d’autre part

M = [ n for n in range(0, 34) if n % 3 == 0 ]
print(M)
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33]

Généralement, ce type de déclaration de liste s’appelle une déclaration par compréhension. La syntaxe est la suivante :

[ <expression(x)> for x in <structure> ]

<expression(x)> est une expression qui peut dépendre d’une variable x, dont la portée reste locale à la liste, et qui varie dans <structure>, un objet itérable (par exemple une autre liste, un itérateur range, etc.).

Voici d’autres exemples :

A = [i for i in range(7)]
print("A =", A)

B =  [i**2 for i in range(-3, 4)]
print("B =", B)

C = [x + 1 for x in B]
print("C =", C)
A = [0, 1, 2, 3, 4, 5, 6]
B = [9, 4, 1, 0, 1, 4, 9]
C = [10, 5, 2, 1, 2, 5, 10]

Par ailleurs, on a vu dnas l’exemple plus haut que l’on peut ajouter une condition après la description de l’itérateur :

[ <expression(x)> for x in <structure> if <condition sur x> ]

<condition sur x> est une condition sur x qui doit être vérifiée pour que l’élément <fonction de x> soit inclus dans la liste. Exemples :

L = [i for i in range(10) if i % 2 == 0]
print(L)

MOTS = ["bonjour", "maison", "ecole",  "voiture", "telephone"]
M = [ mot + "!" for mot in MOTS if len(mot) == 7]
print(M)
[0, 2, 4, 6, 8]
['bonjour!', 'voiture!']

Mots-clefs any et all#

Le mot-clef all permet de tester si toutes les valeurs logiques d’une séquence sont vraies. Par exemple, pour vérifier que tous les entiers d’une liste sont pairs, on peut écrire :

L = [6, 12, -4]
all((x % 2 == 0) for x in L)
True

Ci-dessus, on observe que all prend en entrée une séquence de valeurs logiques. On peut également lui passer en entrée une liste de booléens :

M = ["mot", "clef", "all"]
all([ len(x) == 3 for x in M ])
False

Le mot-clef any teste si au moins une des valeurs logiques passées en paramètre est vraie :

M = ["mot", "clef", "all"]
any(len(x) == 4 for x in M)
True

Un autre exemple :

L = [6, 12, -4]
any(x % 2 == 1 for x in L)
False

Enfin, confomément aux conventions classiques de logique, pour la liste vide, on a respectivement :

all([]), any([])
(True, False)

Ensembles#

Création#

La liste n’est pas la seule structure de données permttant de rassembler des informations. Python permet également de manipuler des ensembles et des dictionnaires.

En informatique, un ensemble peut être vu comme en mathématiques : c’est une collection non-ordonnée d’éléments distincts.

Pour créer un ensemble, on utilise les accolades (comme en mathématiques) :

{ 1, 3 }
{1, 3}

L’ensemble vide peut être construit par la commande set() et représenté par {}.

Comme expliqué précédemment, python stocke un ensemble de manière désordonnée et élimine des potentiels doublons :

A = { 3, 1, "a", 1 }
print(A)
{'a', 1, 3}

Opérations élémentaires#

Comme un ensemble n’est pas ordonné, on ne peut pas accéder à son « élément d’indice \(i\) ». Néanmoins, on peut ajouter, retirer et tester l’appartenance d’un élément à l’ensemble :

S = { 0, 1, 2 }
print(S)

S.add("ajout")
print(S)

S.remove(0)
print(S)

print(1 in S)
{0, 1, 2}
{0, 1, 2, 'ajout'}
{1, 2, 'ajout'}
True

Il est possible de passer d’une liste à un ensemble avec les commandes list et set.

B = { 3, 2, 1 }
L = list(B)
S = set(L)

print(B)
print(L)
print(S)
{1, 2, 3}
[1, 2, 3]
{1, 2, 3}

Enfin, il existe des opérations classiques sur les ensembles :

A = { 0, 1, 2 }
B = { 3, 2, 1 }
print("Union :", A.union(B))
print("Intesection :", A.intersection(B))
print("Différence symétrique :", A.symmetric_difference(B))
Union : {0, 1, 2, 3}
Intesection : {1, 2}
Différence symétrique : {0, 3}

Tableau récapitulatif (ensemble)

Opération sur l’ensemble \(S\)

Syntaxe python

affectation à l’ensemble vide

S = set()

affectation à l’ensemble \(\{1, 2, 7 \}\)

S = { 7, 1, 2} (par exemple)

ajout d’un élément \(x\)

S.add(x)

suppression d’un élément \(y\)

S.remove(y)

union avec un ensemble \(T\)

S.union(T)

intersection avec un ensemble \(T\)

S.intersection(T)

différence symétrique avec un ensemble \(T\)

S.symmetric_difference(T)

test d’appartenance de \(y\)

y in S

Attention, les éléments d’un ensemble python ne peuvent pas être de n’importe quel type : le type doit être hachable (donc, en particulier, immutable). Pour plus d’informations pour cette notion avancée, voir ici. Par exemple, on ne peut pas placer une liste dans un ensemble.

{ [1, 2] }
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[15], line 1
----> 1 { [1, 2] }

TypeError: unhashable type: 'list'

Enfin, les ensembles supportent la déclaration par compréhension (vous remarquerez que l’ordre d’affichage peut ne pas respecter l’ordre de construction) :

{ -x for x in range(12) }
{-11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0}

Dictionnaires#

Création#

Un dictionnaire est une structure de données plus complexe, qui peut être grossièrement vue comme la généralisation d’une liste, où les indices des éléments sont des valeurs quelconques au lieu d’être fixés à \(0, 1, \dots, n-1\).

Par exemple, supposons que l’on souhaite créer une structure de données qui associe à certains mots leurs longueur. On va créer un dictionnaire avec la syntaxe est suivante :

D = { "lundi" : 5, "mardi" : 5, "mercredi" : 8, "jeudi" : 5, "vendredi" : 8, "samedi" : 6, "dimanche" : 8 }
print(D)
{'lundi': 5, 'mardi': 5, 'mercredi': 8, 'jeudi': 5, 'vendredi': 8, 'samedi': 6, 'dimanche': 8}

Les mots « lundi », « mardi », « mercredi », etc. sont appelées les clés du dictionnaire, et les entiers \(5\), \(5\), \(8\), etc. sont les valeurs correspondantes. Ainsi, la syntaxe générale pour déclarer un dictionnaire est la suivante

{ 
  clé1 : valeur1,
  clé2 : valeur2,
  clé3 : valeur3
  ...
  }

Comme pour les ensembles, les clés d’un dictionnaire doivent être hachables, donc, en particulier, une liste ne peut pas être une clé d’un dictionnaire.

Opérations élémentaires#

Si D est un dictionnaire, on accède à la valeur correspondant à une clé k par D[k] (exactement comme avec une liste) :

D["jeudi"]
5

On peut ajouter un couple clé/valeur avec la syntaxe D[clé] = valeur, par exemple :

D["jour"] = 4
print(D)
{'lundi': 5, 'mardi': 5, 'mercredi': 8, 'jeudi': 5, 'vendredi': 8, 'samedi': 6, 'dimanche': 8, 'jour': 4}

Si la clé existait déjà dans le dictionnaire, cet ajout écrase la valeur précédente. Cette syntaxe vaut donc également pour modifier la valeur associée à une clé.

Puis, pour retirer un élément d’un dictionnaire, on peut utiliser la méthode pop (comme pour les listes) :

D.pop("jour")
print(D)
{'lundi': 5, 'mardi': 5, 'mercredi': 8, 'jeudi': 5, 'vendredi': 8, 'samedi': 6, 'dimanche': 8}

On peut tester l’appartenance d’une clé à un dictionnaire avec le mot-clé in, et itérer sur les clés d’un dictionnaire avec la structure for ... in ...:.

print("monday" in D)

for x in D:
    print("Le mot", x, "possède", D[x], "lettres.")
False
Le mot lundi possède 5 lettres.
Le mot mardi possède 5 lettres.
Le mot mercredi possède 8 lettres.
Le mot jeudi possède 5 lettres.
Le mot vendredi possède 8 lettres.
Le mot samedi possède 6 lettres.
Le mot dimanche possède 8 lettres.

Tableau récapitulatif (dictionnaire)

Opération sur le dictionnaire \(D\)

Syntaxe python

affectation au dictionnaire vide

D = dict()

affectation à un dictionnaire non-vide

D = { "a": 1, "bcd": 7 } (par exemple)

accès à la valeur associée à la clé \(c\)

D[c]

ajout d’un couple clé/valeur \((c,v)\)

D[c] = v

modification d’un couple clé/valeur en \((c,v)\)

D[c] = v

suppression de l’élément de clé \(c\)

D.pop(c)

test d’existence d’une clé \(c\)

c in D

Enfin, un dictionnaire python peut être déclaré par compréhension :

L = ["lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"]
E = { jour : len(jour) for jour in L }
print(E)
print(E == D)
{'lundi': 5, 'mardi': 5, 'mercredi': 8, 'jeudi': 5, 'vendredi': 8, 'samedi': 6, 'dimanche': 8}
True