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
) vautFalse
. - Les conteneurs vides (chaîne vide, liste vide) valent
False
. - Toute valeur qui ne vaut pas explicitement
False
vautTrue
.
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
vautFalse
, le résultat sera forcémentFalse
. Doncand
fait un raccourci et ne regarde même pasb
. Dans ce cas la valeur renvoyée esta
(qui peut être interprétée commeFalse
). - Si
a
vautTrue
, alorsand
renverra simplementb
, puisque la conversion deb
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'
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'
>>> bin(0b101010 ^ 0b111000)
'0b10010'
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