On vient de voir que la méthode items
des dictionnaires renvoyait des couples de valeurs.
Mais qu’est-ce que c’est au juste qu’un couple, un nouveau type ?
Oui, il s’agit d’un tuple.
Les tuples
Les tuples (parfois traduits en n-uplets) sont des équivalents non modifiables aux listes. C’est-à-dire des séquences d’un nombre fixe d’éléments : après la définition, on ne peut ni ajouter, ni supprimer, ni remplacer d’élément.
Un tuple est généralement défini par une paire de parenthèses contenant les éléments séparés par des virgules. Comme une liste, un tuple peut contenir des éléments de types différents.
>>> (1, 2, 3)
(1, 2, 3)
>>> ('a', 'b', 'c')
('a', 'b', 'c')
>>> (42, '!')
(42, '!')
On notera tout de même que les parenthèses sont facultatives, c’est la virgule qui définit réellement un tuple. Comme pour les opérations arithmétiques, les parenthèses servent en fait à gérer les priorités et mettre en valeur le tuple.
>>> 1, 2, 3
(1, 2, 3)
>>> 1, 2, 3 * 3
(1, 2, 9)
>>> (1, 2, 3) * 3
(1, 2, 3, 1, 2, 3, 1, 2, 3)
Il faut bien penser à cette virgule lorsque l’on cherche à définir un tuple contenant un unique élément.
En effet, (1)
étant une notation équivalente à 1
, il est nécessaire d’en ajouter une pour expliciter le tuple.
>>> (1)
1
>>> (1,)
(1,)
>>> 1,
(1,)
Par ailleurs, il est possible de définir un tuple vide à l’aide d’une simple paire de parenthèses (il n’y a dans ce cas pas de confusion avec d’autres utilisations possibles des parenthèses).
>>> ()
()
J’utiliserai principalement le terme de tuple, mais il faut savoir qu’on rencontre parfois d’autres noms suivant la taille du tuple. On parle ainsi parfois de couple pour des tuples de 2 éléments, des triplets pour 3, etc.
Par exemple il est courant de dire que la méthode items
des dictionnaires renvoie des couples clé/valeur.
>>> phonebook = {'Alice': '0633432380', 'Bob': '0663621029', 'Alex': '0714381809'}
>>> for couple in phonebook.items():
... print(couple)
...
('Alice', '0633432380')
('Bob', '0663621029')
('Alex', '0714381809')
Opérations sur les tuples
Les opérations sont semblables à celles des listes.
Il est possible de convertir un itérable en tuple en appelant le type tuple
comme une fonction.
>>> tuple([1, 2, 3])
(1, 2, 3)
>>> tuple('abcd')
('a', 'b', 'c', 'd')
On peut accéder aux éléments d’un tuple (en lecture uniquement) avec l’opérateur d’indexation []
, qui gère les index négatifs et les slices.
>>> values = (4, 5, 6)
>>> values[1]
5
>>> values[-1]
6
>>> values[::2]
(4, 6)
in
permet de vérifier si une valeur est présente dans le tuple.
>>> 3 in values
False
>>> 4 in values
True
On peut concaténer deux tuples avec +
, et multiplier un tuple par un nombre avec *
.
>>> (4, 5, 6) + (7, 8, 9)
(4, 5, 6, 7, 8, 9)
>>> (4, 5, 6) * 2
(4, 5, 6, 4, 5, 6)
Les tuples sont ordonnables les uns par rapport aux autres, de la même manière que les listes.
>>> (1, 2, 3) < (1, 2, 4)
True
>>> (1, 2, 3) <= (1, 2, 2)
False
Les fonctions len
, min
, max
, all
, any
etc. sont aussi applicables aux tuples.
>>> len(values)
3
>>> min(values)
4
>>> max(values)
6
>>> all((True, True, False))
False
>>> any((True, True, False))
True
Enfin, les tuples sont pourvus de deux méthodes, index
et count
, pour respectivement trouver la position d’un élément et compter les occurrences d’un élément.
>>> values.index(6)
2
>>> values.count(6)
1
Utilisations des tuples
On peut parfois se demander quand utiliser un tuple et quand utiliser une liste. Le tuple étant comparable à une liste non modifiable, il peut donc être utilisé pour toutes les opérations attendant une liste et ne cherchant pas à la modifier. Il est même préférable de l’utiliser si l’on sait qu’il ne sera jamais question de modification, ou si l’on veut empêcher toute modification.
Mais il y a aussi des opérations qui ne sont possibles qu’avec les tuples. Étant non modifiables, ils peuvent être utilisés en tant que clés de dictionnaires.
>>> cells = {(0, 0): 'x', (0, 1): '.', (1, 0): '.', (1, 1): 'x'}
>>> cells[(1, 0)]
'.'
>>> cells[(1, 1)] = ' '
>>> cells
{(0, 0): 'x', (0, 1): '.', (1, 0): '.', (1, 1): ' '}
Les parenthèses sont encore une fois facultatives lors des accès.
>>> cells[0, 0]
'x'
Cette structure permet ainsi de représenter d’une grille de données où chaque case est associée à ses coordonnées.
Attention cependant, un tuple qui contient un élément modifiable pourra lui aussi être indirectement altéré.
Par exemple si un tuple contient une liste, rien n’empêche d’ajouter des éléments à cette liste.
>>> events = ('29/05/2019', ['anniversaire', 'soirée'])
>>> events[1].append('rdv coiffeur')
>>> events
('29/05/2019', ['anniversaire', 'soirée', 'rdv coiffeur'])
Un tel tuple ne pourra donc pas être utilisé comme clé de dictionnaire, parce qu’il contient une liste qui ne peut pas être utilisée comme tel.
>>> {events: None}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
Mais beaucoup d’utilisations des tuples sont tous simplement implicites. C’est en effet une manière de faire des assignations multiples de variables.
>>> a, b = 1, 2
>>> a
1
>>> b
2
Techniquement, cela revient à écrire (a, b) = (1, 2)
, ou encore :
>>> tmp = (1, 2)
>>> (a, b) = tmp
On appelle cette seconde opération (assigner plusieurs variables depuis un tuple) l'unpacking, mais nous y reviendrons plus tard.