Retour sur les types précédents

Mais avant d’aller plus loin, il serait bon de refaire un tour d’horizon des types vus précédemment, de revoir leurs opérations et méthodes.

Généralités

Une valeur en Python peut-être le résultat de n’importe quelle expression (opération, appel de fonction, accès à une variable, etc.). Toute valeur possède un type qui définit les opérations qui lui sont applicables.

Conversions

Certaines valeurs peuvent être converties d’un type vers un autre. Pour cela, les types s’utilisent comme des fonctions, où la valeur à convertir est donnée en argument.

>>> int('123')
123
>>> float(42)
42.0
>>> list('abc')
['a', 'b', 'c']
>>> str(1.5)
'1.5'
Comparaisons

Les opérateurs d’égalité (==) et de différence (!=) sont applicables à tous les types.

>>> 2 == 2
True
>>> 1.5 == 3.7
False
>>> 'abc' != 'def'
True
>>> [1, 2, 3] == [1, 2, 3]
True

Ces opérations sont de plus compatibles entre valeurs de types différents.

>>> 2 == 2.0
True
>>> 2 == 2.5
False
>>> 2 != '2'
True
>>> 2 == [2]
False

Booléens

Le type booléen (bool) permet de représenter les valeurs True (vrai) et False (faux). Ces valeurs peuvent être le résultat d’une opération booléenne comme les opérateurs de comparaison (==, !=, <, etc.).

Conversions

Toute valeur Python peut être interprétée comme un booléen (par conversion implicite) :

  • Le nombre zéro (0, 0.0) vaut False.
  • Les conteneurs vides (chaîne vide, liste vide) valent False.
  • Toute valeur qui ne vaut pas explicitement False vaut True.

Il est aussi possible de convertir explicitement une valeur en booléen en faisant appel au type booléen. Les règles de conversion sont les mêmes que celles énoncées ci-dessus.

>>> bool(5)
True
>>> bool(0.0)
False
>>> bool('abc')
True
>>> bool([])
False
Opérations

Trois opérateurs existent sur les booléens : not (unaire), and et or (binaires), répondant chacun à une table de vérité.

a not a
True False
False True
a b a and b
True True True
True False False
False True False
False False False
a b a or b
True True True
True False True
False True True
False False False

Ces opérateurs sont présentés comme renvoyant toujours True ou False, mais ce n’est en vérité pas toujours le cas. Étant donné que toute valeur peut être vue comme un booléen, il suffit de renvoyer une valeur qui sera interprétée comme True ou False.

Prenons le cas de and avec une opération a and b :

  • Si a vaut False, le résultat sera forcément False. Donc and fait un raccourci et ne regarde même pas b. Dans ce cas la valeur renvoyée est a (qui peut être interprétée comme False).
  • Si a vaut True, alors and renverra simplement b, puisque la conversion de b en booléen sera le résultat de l’opération.
>>> [] and 5
[]
>>> ['foo'] and 5
5
>>> ['foo'] and 0
0
>>> 5 and True
True

Le même genre de raccourci existe pour or, qui renvoie a si a vaut True et b sinon.

>>> ['foo'] or 5
['foo']
>>> [] or 5
5
>>> [] or 0
0
>>> 0 or True
True

On notera enfin en termes de conversions que les booléens eux-mêmes sont aussi implicitement convertis en nombres lorsque utilisés comme tels. On aura ainsi True converti en 1 et False en 0.

>>> False + 2 * True
2

Nombres

Nous avons rencontré deux types pour représenter les nombres : les entiers et les flottants (nombres à virgule). Les premiers ne représentent que des nombres entiers, avec une précision infinie (il n’y a pas de limite), les seconds représentent des nombres réels mais avec une précision limitée.

Conversions

On peut facilement convertir des valeurs en int ou float en faisant appel à ces types comme à des fonctions.

>>> int('42')
42
>>> float('4.5')
4.5
>>> int(4.5)
4
>>> int(float('4.5'))
4

Toute valeur n’est pas convertible en nombre, des erreurs peuvent donc survenir si l’argument est invalide.

>>> int('4.5') # 4.5 n'est pas un nombre entier valide
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '4.5'
Opérations

Beaucoup d’opérations sont applicables sur les nombres, et les deux types sont compatibles entre eux. On retrouve d’abord les opérations arithmétiques : addition (+), soustraction (-), multiplication (*), division (/), division euclidienne (//), modulo (%) et puissance (**).

>>> 1 + 5
6
>>> 4.3 - 2
2.3
>>> 1.5 * 4
6.0
>>> 7 / 5
1.4
>>> 7 // 5
1
>>> 7 % 5
2
>>> 2 ** 3
8

On a aussi tous les opérateurs de comparaison, qui renvoient des valeurs booléennes : l’égalité (==), la différence (!=), l’infériorité (<, <=) et la supériorité (>, >=).

>>> 3 == 3.0
True
>>> 1 != 2
True
>>> 3 < 4.0
True
>>> 4 > 4.0
False
>>> 4 >= 4.0
True

Et d’autres opérateurs ne sont accessibles que via des fonctions : la valeur absolue (abs), l’arrondi (round), le minimum (min), le maximum (max) et la division euclidienne avec reste (divmod).

>>> abs(-1.2)
1.2
>>> round(1/3, 4)
0.3333
>>> min(1.5, -6, 3.7)
-6
>>> max(1.5, -6, 3.7)
3.7
>>> divmod(7, 5)
(1, 2)
Représentations des entiers

On sait que l’on peut convertir un nombre en chaîne de caractères en appelant str, qui utilise la représentation décimale (en base 10), mais d’autres représentations sont possibles pour les entiers. bin permet d’avoir la représentation binaire (base 2), oct pour l’octale (base 8) et hex pour l’hexadécimale (base 16).

>>> bin(42)
'0b101010'
>>> oct(42)
'0o52'
>>> hex(42)
'0x2a'

Ces représentations sont d’ailleurs parfaitement valides pour être entrées en tant que nombre dans l’interpréteur, qui les analysera donc selon leur préfixe (0b, 0o ou 0x).

>>> 0b101010
42
>>> 0o52
42
>>> 0x2a
42

Puisqu’on en est à parler des bases, tout nombre peut ainsi être considéré comme une succession de bits (tel que la représentation renvoyée par bin). Un bit étant soit 0 soit 1, on peut même parler de tableau de booléens.

Différents opérateurs — à rapprocher des opérateurs booléens — tirent parti de cette particularité pour offrir des opérations bit-à-bit sur les nombres.

Ainsi, l’opérateur ET (&) calcule le nombre résultat de l’application d’un ET binaire (and) entre chaque bit de deux nombres.

>>> bin(0b101010 & 0b111000)
'0b101000'
101010&111000=101000\begin{array}{rcccccc} & \color{blue}1 & \color{blue}0 & \color{blue}1 & \color{blue}0 & \color{blue}1 & \color{blue}0 \\ \& & \color{red}1 & \color{red}1 & \color{red}1 & \color{red}0 & \color{red}0 & \color{red}0 \\ \hline = & 1 & \color{blue}0 & 1 & 0 & \color{red}0 & 0 \end{array}

J’utilise ici des représentations binaires pour que le calcul soit plus lisible, mais l’opérateur s’applique simplement sur des entiers et renvoie un entier.

>>> 42 & 56
40

De la même manière, on a les opérateurs OU-inclusif (|) et OU-exclusif/XOR (^).

>>> bin(0b101010 | 0b111000)
'0b111010'
101010111000=111010\begin{array}{rcccccc} & \color{blue}1 & \color{blue}0 & \color{blue}1 & \color{blue}0 & \color{blue}1 & \color{blue}0 \\ \vert & \color{red}1 & \color{red}1 & \color{red}1 & \color{red}0 & \color{red}0 & \color{red}0 \\ \hline = & 1 & \color{red}1 & 1 & 0 & \color{blue}1 & 0 \end{array}
>>> bin(0b101010 ^ 0b111000)
'0b10010'
101010^111000=010010\begin{array}{rcccccc} & \color{blue}1 & \color{blue}0 & \color{blue}1 & \color{blue}0 & \color{blue}1 & \color{blue}0 \\ \hat{} & \color{red}1 & \color{red}1 & \color{red}1 & \color{red}0 & \color{red}0 & \color{red}0 \\ \hline = & \color{violet}0 & \color{red}1 & \color{violet}0 & 0 & \color{blue}1 & 0 \end{array}

Notez que le premier zéro n’apparaît pas dans le résultat renvoyé par Python pour le XOR, mais 0b10010 et 0b010010 sont bien deux représentations du même nombre (18).

D’autres opérations bit-à-bit sont encore possibles (~, <<, >>), vous pourrez en apprendre plus sur cette page dédiée aux opérateurs.

Précision des flottants

Les nombres flottants en Python ont une précision limitée, c’est-à-dire qu’ils auront du mal à représenter des nombres trop grands ou avec trop de chiffres après la virgule.

>>> 0.10000000000000001
0.1

On voit ici que le dernier 1 s’est perdu. C’est dû au fait que ces nombres sont stockés sur une zone mémoire de taille fixe, et que des arrondis sont nécessaires dans certains cas.
On peut le voir aussi sur d’autres opérations qui produisent normalement des nombres infinis.

>>> 1/3
0.3333333333333333
>>> 7/6
1.1666666666666667

Par ailleurs, les nombres y sont stockés en base 2, et certains nombres qui nous paraissent finis (0.1) ne le sont pas en binaire (il faut une infinité de chiffres derrière la virgule pour représenter 0.1 en base 2). C’est pourquoi des arrondis sont effectués sur ces nombres. Ils ne sont pas toujours visibles, mais ils peuvent apparaître à certains moments et être source de bugs.

>>> 0.1 + 0.1 + 0.1
0.30000000000000004

En raison de ces arrondis il est plutôt déconseillé de comparer deux flottants avec ==, puisque cela pourrait amener à un résultat incohérent. Nous verrons dans la suite du cours comment résoudre ce problème.

>>> 0.1 + 0.1 + 0.1 == 0.3
False
Notation des flottants

123.456 est la notation habituelle des nombres flottants, mais une autre est possible : la notation scientifique. Il s’agit de représenter un nombre avec un exposant d’une puissance de 10. Cela aide à écrire les nombres très grands ou très petits.

Par exemple, 3.2e5 est égal à 3.2 * 10**5 soit 320000.0, et 4e-3 à 4.0 * 10**-3 donc 0.004

>>> 3.2e5
320000.0
>>> 4e-3
0.004

Pour certains nombres, trop grands/petits pour être représentés correctement avec la notation habituelle, Python basculera automatiquement en notation scientifique.

>>> 9.6 ** 100
1.6870319358849588e+98
>>> 2 / 10000000000
2e-10

Enfin, il est aussi possible avec les flottants de représenter les infinis (positif et négatif), mais ils ne sont pas directement accessibles. On peut accéder à l’infini positif à l’aide de l’expression float('inf').

>>> inf = float('inf')
>>> inf
inf
>>> inf + 2
inf
>>> inf * inf
inf
>>> 1 / inf
0.0

L’infini sera toujours supérieur à n’importe quel autre nombre.

>>> inf > 10**100
True

De façon similaire, on retrouve l’infini négatif avec float('-inf').

Nombres complexes

Vous pouvez passer cette section si vous n’êtes pas familiers des nombres complexes, ce n’est pas important pour la suite.

Python embarque aussi nativement les nombres complexes qui sont accessibles via le suffixe j pour représenter la partie imaginaire. Les complexes sont un sur-ensemble des flottants, et les mêmes opérations sont donc applicables sur eux.

>>> 1+2j + 4+5j
(5+7j)
>>> 0.5j + 3.2+9.3j
(3.2+9.8j)
>>> (1+2j) * (4+5j)
(-6+13j)
>>> 1j*1j
(-1+0j)
>>> (1+2j) ** 2
(-3+4j)

Par ailleurs, on trouve sur ces nombres des attributs real et imag pour accéder aux parties réelle et imaginaire, et une méthode conjugate pour calculer le conjugué.

>>> c = 1+2j
>>> c.real
1.0
>>> c.imag
2.0
>>> c.conjugate()
(1-2j)

Bien sûr, les nombres complexes ne sont par ordonnables entre eux.

>>> 1+2j < 2+1j
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'complex' and 'complex'

Enfin, la fonction abs (valeur absolue) permet aussi de calculer le module d’un nombre complexe.

>>> abs(3+4j)
5.0

Chaînes de caractères

La chaîne de caractère est le type utilisé pour représenter du texte, on peut la voir comme une séquence (ou un tableau) de caractères.

Conversions

Toute valeur Python est convertible en chaîne de caractères, en faisant appel à str.

>>> str(True)
'True'
>>> str(4)
'4'
>>> str(1.5)
'1.5'
>>> str('foo')
'foo'
>>> str([1, 2, 3])
'[1, 2, 3]'

C’est ainsi que print procède d’ailleurs pour afficher n’importe quelle valeur.

Opérations

La longueur d’une chaîne peut être obtenue par un appel à la fonction len.

>>> len('foo')
3
>>> len('hello world')
11
>>> len('')
0
Indexation

On peut accéder aux différents caractères de la chaîne à l’aide de l’opérateur d’indexation [] accompagné d’un index (une position dans la chaîne, à partir de 0). Cet index peut être négatif pour parcourir la chaîne depuis la fin.

>>> 'hello world'[1]
'e'
>>> 'hello world'[-3]
'r'

On peut préciser un intervalle d’index grâce au slicing avec la syntaxe debut:fin:pas où chaque élément est optionnel.

>>> 'hello world'[3:]
'lo world'
>>> 'hello world'[:-4]
'hello w'
>>> 'hello world'[1:8:2]
'el o'
Concaténation

Il est possible de concaténer (mettre à la suite) plusieurs chaînes de caractères avec l’opérateur +.

>>> 'hello' + ' ' + 'world' + '!'
'hello world!'

On peut aussi « multiplier » une chaîne par un nombre entier n pour obtenir n concaténations de cette même chaîne.

>>> 'hello ' * 3
'hello hello hello '
Relations d’ordre

Les chaînes de caractères sont ordonnées les unes par rapport aux autres, il est donc possible d’utiliser les opérateurs <, >, <= et >= entre deux chaînes.

La comparaison est faite en fonction de l’ordre lexicographique, une extension de l’ordre alphabétique.

>>> 'abc' < 'def'
True
>>> 'abc' > 'def'
False
Appartenance

L’opérateur in permet de tester si une chaîne contient un caractère ou une sous-chaîne (ou vu autrement, si cette sous-chaîne appartient à la chaîne). L’opération renvoie un booléen.

>>> 'h' in 'hello'
True
>>> 'lo' in 'hello'
True
>>> 'la' in 'hello'
False
Principales méthodes

Les méthodes lstrip, rstrip et strip permettent respectivement de renvoyer une nouvelle chaîne en supprimant les espaces au début, à la fin ou des deux côtés.

>>> '  foo bar  '.lstrip()
'foo bar  '
>>> '  foo bar  '.rstrip()
'  foo bar'
>>> '  foo bar  '.strip()
'foo bar'

Elles acceptent un argument optionnel pour supprimer des caractères en particulier plutôt que des espaces.

>>> '...hello...'.strip('.')
'hello'
>>> '.-hello-..'.strip('.-')
'hello'

Attention, l’argument donné à strip spécifie un ensemble de caractères à supprimer et non une chaîne précise. s.strip('.-') et s.strip('-.') sont équivalents.

Les méthodes upper, lower, capitalize et title permettent d’obtenir une nouvelle chaîne en changeant la casse des caractères.

>>> 'HeLlO wOrLd!'.upper()
'HELLO WORLD!'
>>> 'HeLlO wOrLd!'.lower()
'hello world!'
>>> 'HeLlO wOrLd!'.capitalize()
'Hello world!'
>>> 'HeLlO wOrLd!'.title()
'Hello World!'

index et find servent à trouver la première position d’un caractère (ou d’une sous-chaîne) dans une chaîne.

index produit une erreur si le caractère n’est pas trouvé, find renvoie -1.

>>> 'hello world'.index('o')
4
>>> 'hello world'.find('h')
0
>>> 'hello world'.index('world')
6
>>> 'hello world'.find('world')
6
>>> 'hello'.index('w')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: substring not found
>>> 'hello'.find('w')
-1

Il est possible de compter le nombre d’occurrences d’un caractère (ou d’une sous-chaîne) avec la méthode count.

>>> 'hello world'.count('o')
2
>>> 'toto'.count('to')
2

On peut tester spécifiquement si une chaîne commence ou termine par une autre avec les méthodes startswith et endswith. Ces méthodes renvoient un booléen.

>>> 'hello world'.startswith('hello')
True
>>> 'hello world'.endswith('hello')
False
>>> 'hello world'.startswith('world')
False
>>> 'hello world'.endswith('world')
True

Depuis Python 3.9, les chaînes de caractères possèdent aussi des méthodes removeprefix et removesuffix qui permettent de retirer une sous-chaîne au début ou à la fin de notre chaîne.
Ces méthodes ne produisent pas d’erreur si la sous-chaîne n’est pas trouvée et renvoient juste la chaîne telle quelle.

>>> 'helloworld'.removeprefix('hello')
'world'
>>> 'helloworld'.removesuffix('world')
'hello'
>>> 'helloworld'.removeprefix('world')
'helloworld'

Différents tests sont possibles sur les chaînes de caractères pour savoir si elles sont composées de caractères alphanumériques (isalnum), alphabétiques (isalpha), numériques (isdigit) et d’autres encore.

>>> 'salut123'.isalnum()
True
>>> 'salut 123'.isalnum()
False
>>> 'salut'.isalpha()
True
>>> 'salut123'.isalpha()
False
>>> '123'.isdigit()
True
Méthodes avancées

La méthode replace permet de renvoyer une copie de la chaîne en remplaçant un caractère (ou une sous-chaîne) par un autre.

>>> 'hello world'.replace('o', 'a')
'hella warld'
>>> 'hello world'.replace('ll', 'xx')
'hexxo world'
>>> 'hello world'.replace('ll', '')
'heo world'

On peut découper une chaîne de caractères vers une liste de chaînes à partir d’un séparateur (caractère ou sous-chaîne) avec la méthode split. Par défaut, le séparateur est l’espace.

>>> 'hello world'.split()
['hello', 'world']
>>> 'abc:def:ghi'.split(':')
['abc', 'def', 'ghi']
>>> 'abc : def : ghi'.split(' : ')
['abc', 'def', 'ghi']

Ce séparateur ne peut pas être une chaîne vide.

>>> 'hello'.split('')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: empty separator

Enfin, il est possible d’unir les chaînes de caractère d’une liste autour d’un séparateur en utilisant la méthode join sur ce séparateur.

>>> ' '.join(['hello', 'world'])
'hello world'
>>> ':'.join(['abc', 'def', 'ghi'])
'abc:def:ghi'

La chaîne vide est ici acceptée pour concaténer directement les chaînes.

>>> ''.join(['h', 'e', 'l', 'l', 'o'])
'hello'

Listes

Les listes représentent des tableaux de valeurs de tous types. Contrairement aux types précédents, les listes sont des objets modifiables (leur valeur peut varier avec le temps).

Conversions

Une chaîne de caractères étant une séquence, elle peut être convertie en liste de caractères en faisant appel à list.

>>> list('hello')
['h', 'e', 'l', 'l', 'o']

Cela peut justement permettre de récupérer l’équivalent modifiable d’une chaîne de caractères.

>>> txt = list('hello')
>>> txt[1] = 'a'
>>> ''.join(txt)
'hallo'
Opérations

On retrouve pour les listes les opérations d’indexation ([]), de concaténation (+, *) et d’appartenance (in).

L’indexation permet cependant de modifier une liste en assignant une valeur à une position et d’en supprimer avec del.

>>> values = [3, 4, 5]
>>> values[0]
3
>>> values[1:]
[4, 5]
>>> values[-1] = 6
>>> del values[0]
>>> values
[4, 6]
>>> [1, 2] + values
[1, 2, 4, 6]
>>> values * 2
[4, 6, 4, 6]
>>> 4 in [1, 2, 3]
False
>>> 4 in [1, 2, 4]
True

Contrairement aux chaînes de caractères, l’opérateur in n’ira pas chercher de sous-liste dans une liste.

>>> [1, 2] in [1, 2, 3]
False
>>> [1, 2] in [[1, 2], [3, 4]]
True

Au niveau de la multiplication d’une liste par un nombre, il faut bien faire attention aux cas de références multiples. Quand on multiplie ainsi une liste, on ne copie pas les éléments qu’elle contient, mais on ne fait que les dupliquer. On a donc plusieurs fois un même objet dans la liste.

Ce n’est pas gênant pour des valeurs non modifiables (nombres, chaînes), mais si une liste contient d’autres listes cela peut vite devenir problématique.

>>> table = [[0, 0, 0]] * 2
>>> table
[[0, 0, 0], [0, 0, 0]]
>>> table[0][1] = 5
>>> table
[[0, 5, 0], [0, 5, 0]]

Les opérateurs d’ordre (<, >) sont aussi utilisables entre deux listes, leur résultat dépend de la comparaison entre les éléments des listes, par ordre lexicographique.

C’est-à-dire qu’on commence par comparer les premiers éléments des deux listes : s’ils sont différents, alors la liste dont l’élément est le plus grand est considérée comme supérieure.

>>> [3, 0, 0] > [1, 9, 9]
True
>>> [3, 0, 0] < [1, 9, 9]
False
>>> [3, 0, 0] < [4, 9]
True
>>> [1, 2, 3] < [2]
True
>>> ['abc', 'def'] < ['ghi']
True

Mais s’ils sont égaux, l’opération continue en passant aux éléments suivants, et ainsi de suite jusqu’à l’épuisement de l’une des listes. Une liste qui est épuisée avant l’autre est considérée comme inférieure. Ainsi [1, 2, 3] est inférieure à [1, 2, 3, 4].

>>> [1, 2, 3] < [1, 2, 4]
True
>>> [1, 2, 3] < [1, 2, 2]
False
>>> [1, 2, 3] < [1, 2, 3, 4]
True
>>> [1, 2, 3, 9] < [1, 2, 4]
True
>>> [1, 2, 3] < [1]
False
>>> ['abc', 'def'] > ['abc']
True

Dans le cas où les éléments des deux listes ne sont pas ordonnables, on obtient une erreur de type signifiant que la comparaison est impossible.

>>> [1, 2] < [1, 'a']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'int' and 'str'

Et on retrouve bien sûr les opérateurs d’inégalités <= et >=.

>>> [3, 2, 1] > [3, 2, 1]
False
>>> [3, 2, 1] >= [3, 2, 1]
True
>>> [3, 2, 1] <= [3, 2, 1]
True

D’autres opérateurs prennent la forme de fonctions. C’est le cas de len pour récupérer la taille d’une liste.

>>> len(['a', 'b', 'c'])
3

On a aussi les fonctions min et max pour récupérer le plus petit ou le plus grand élément d’une liste.

>>> min([3, 1, 2])
1
>>> max(['z', 'c', 'a', 'y'])
'z'

sum est une fonction qui opère sur une liste de nombres et en calcule la somme.

>>> sum([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
55

Enfin je voulais aussi vous présenter les fonctions all et any, qui agissent comme des and/or sur l’ensemble des éléments d’une liste, mais renvoient un booléen dans tous les cas. all vérifie que tous les éléments sont vrais, et any qu’au moins un élément est vrai.

Ainsi, all([a, b, c, d]) est équivalent à a and b and c and d et any([a, b, c, d]) à a or b or c or d.

>>> all([1, 2, 3, 4])
True
>>> all([1, 2, 3, 4])
True
>>> all([0, 1, 2, 3, 4])
False
>>> any([0, 1, 2, 3, 4])
True
>>> any([0])
False

Attention cependant au comportement sur les listes vides : all s’attend à ce que tous les éléments soient vrais ; mais si la liste ne contient aucun élément, alors techniquement ils sont bien tous vrais. De même pour any qui veut au moins un élément vrai, ce qui ne peut pas être le cas s’il n’y a aucun élément.

>>> all([])
True
>>> any([])
False
Principales méthodes

Venons-en maintenant à quelques méthodes sur les listes.

Comme sur les chaînes, on a une méthode index pour rechercher le premier index d’un élément.

>>> values = ['a', 'b', 'c', 'd']
>>> values.index('c')
2

Les méthodes append, insert, pop et clear permettent de modifier la liste en ajoutant / insérant / supprimant un élément, ou en la vidant.

>>> values.append('e') 
>>> values.insert(3, 'ç')
>>> values.pop(1)
'b'
>>> values
['a', 'c', 'ç', 'd', 'e']
>>> values.clear()
>>> values
[]

Les listes ont aussi une méthode remove pour supprimer un élément en fonction de sa valeur plutôt que son index.

>>> values = ['a', 'b', 'c', 'd']
>>> values.remove('c')
>>> values
['a', 'b', 'd']

La méthode extend permet d’ajouter une liste d’éléments à la fin, ce qui revient à concaténer la liste donnée en argument dans la liste actuelle.

>>> values.extend(['c', 'e', 'f'])
>>> values
['a', 'b', 'd', 'c', 'e', 'f']

Quelques méthodes permettent de faire varier l’ordre des éléments dans la liste. C’est le cas de reverse qui inverse l’ordre des éléments.

>>> values.reverse()
>>> values
['f', 'e', 'c', 'd', 'b', 'a']

sort permet quant à elle de trier les éléments du plus petit au plus grand.

>>> values.sort()
>>> values
['a', 'b', 'c', 'd', 'e', 'f']

Il est possible de passer un booléen comme argument nommé reverse pour trier les éléments dans l’autre sens.

>>> values.sort(reverse=True)
>>> values
['f', 'e', 'd', 'c', 'b', 'a']

Enfin, on a vu plus haut les problèmes que pouvaient causer les multiples références sur une même liste. Parfois, on veut simplement deux listes contenant les mêmes valeurs mais indépendantes l’une de l’autre, et l’on doit pour cela en réaliser une copie. Les listes possèdent pour cela une méthode copy.

>>> other_values = values.copy()
>>> values.append('g')
>>> values
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> other_values
['a', 'b', 'c', 'd', 'e', 'f']

Ce même comportement est aussi possible en appelant list sur une liste existante, ou en utilisant un slicing vide.

>>> list(values)
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> values[:]
['a', 'b', 'c', 'd', 'e', 'f', 'g']

Attention cependant avec les listes multidimensionnelles : copy ne réalise une copie que du premier niveau de la liste.

Ainsi, avec le code qui suit, nous aurons encore des références communes entre les deux listes.

>>> values = [['a', 'b', 'c'], ['d', 'e', 'f']]
>>> other_values = values.copy()
>>> values[1].append('g')
>>> other_values
[['a', 'b', 'c'], ['d', 'e', 'f', 'g']]

Nous verrons par la suite comment réaliser une copie en profondeur et éviter ce problème.

Mais cela ne concerne bien sûr que les dimensions imbriquées : values et other_values restent deux listes distinctes.

>>> values.append(['h', 'i', 'j'])
>>> values
[['a', 'b', 'c'], ['d', 'e', 'f', 'g'], ['h', 'i', 'j']]
>>> other_values
[['a', 'b', 'c'], ['d', 'e', 'f', 'g']]
Identité

Il existe en Python un opérateur d’identité, l’opérateur is. Celui-ci permet de tester si deux valeurs sont un seul et même objet, et non simplement des valeurs égales.

Il permet ainsi de savoir si deux variables pointent vers une même liste ou vers deux listes distinctes.

>>> values = [1, 2, 3]
>>> other_values = values
>>> other_values is values
True
>>> other_values = values.copy()
>>> other_values is values
False
>>> other_values == values
True

À l’inverse, on trouve l’opérateur is not pour tester la non-identité.

>>> other_values is not values
True

None

None est une valeur particulière en Python, qui représente l’absence de valeur. On l’a déjà rencontrée sans vraiment y faire attention.

C’est par exemple la valeur renvoyée par les fonctions ou méthodes qui ne renvoient « rien ».

>>> [].clear()
>>> print([].clear())
None

La fonction print en elle-même renvoie None.

>>> print(print())

None

Dans certains traitements, il est parfois utile de savoir si l’on a affaire à None ou à une autre valeur. Pour vérifier ça, on serait tenté de tester si notre valeur est égale à None avec un ==.

Mais None est une valeur unique en Python, il n’en existe qu’un (on parle de singleton) et on préférera donc utiliser l’opérateur d’identité : is.

>>> None is None
True
>>> [].clear() is None
True
>>> abs(-5) is None
False

On retrouve aussi l’opérateur is not pour vérifier qu’une valeur n’est pas None.

>>> abs(-5) is not None
True
>>> [].clear() is not None
False