{{tag>cours python dev tuple todo}}
======= Python: les tuples ======
Nous introduisons ici un autre type built-in qui s'appelle **le tuple**. Le tuple est très proche de la liste. Comme une liste, c'est une séquence. On peut donc appliquer les opérations comme le test d'appartenance avec **in**, accéder aux différents éléments avec **[]**, faire du **slicing**. Comme la liste, un tuple peut référencer des objets complètement hétérogènes. C'est très proche de la liste, mais il y a une différence fondamentale entre la liste et le tuple, c'est que le tuple est un **objet immuable**. Ça veut dire qu'une fois qu'on a créé le tuple, on ne peut plus le modifier. Nous verrons la raison fondamentale de l'existence du tuple qui est immuable lorsque nous aborderons les dictionnaires.
Commençons par créer **un tuple vide**. On crée un tuple en écrivant simplement des parenthèses ouvrante et fermante. Ça va donc me créer un objet de type tuple, je peux le vérifier avec type, voilà, c'est un objet tuple qui est simplement vide. Évidemment, comme le tuple est immuable, lorsque je crée un tuple vide, je ne peux rien ajouter donc ce tuple vide a assez peu d'intérêt.
# instancier un tuple vide
>>> t1 = ()
# on vérifie que l'objet est bien un tuple
>>> type(t1)
tuple
Pour créer **un tuple avec un élément**, attention à la notation:
>>> t = (4,)
>>> type(t)
tuple
>>> len(t)
1
Vous remarquez qu'on a rajouté une virgule derrière le seul élément. Si vous écrivez ''(t = 4)'' avec des parenthèses sans virgule, pour Python, les parenthèses vont simplement permettre de grouper des opérations, et par conséquent, il va considérer qu'en fait l'objet que vous avez créé est juste un entier qui vaut 4. Donc pour un **tuple singleton**, un tuple d'un seul élément, **il ne faut pas oublier de mettre la virgule**.
Ensuite, on peut créer un tuple de plusieurs éléments, qui contient des objets complètement hétérogènes, exactement comme une liste:
>>> t = (True, 3.4, 18)
# Une caractéristique importante du tuple, c'est que les parenthèses sont facultatives
>>> t2 = True, 3.4, 18
# tuple singleton
>>> t3 = 3,
Nous allons voir dans quelques instants pourquoi ces parenthèses ne sont pas nécessaires pour définir un tuple.
Comme le tuple est un objet de type séquence, je peux évidemment faire toutes les opérations que je peux faire sur une séquence.
# test d'appartenance
>>> 3.4 in t2
True
# accéder à un élément du tuple avec la notation crochets
>>> t2[1]
3.4
# slicing
>>> t2[:2]
(True, 3.4)
**On peut convertir un tuple en liste**:
>>> l = list(t2)
# la liste est mutable, on peut apporter des modifications
>>> l.append("ajout")
>>> l[0] = False
# on peut ensuite passer d'une liste à un tuple
>>> t2 = tuple(l)
>>> type(t2)
tuple
>>> print(t2)
(False, 3.4, 18, 'ajout')
C'est très important de comprendre cela, le tuple étant immuable, nous n'avons pas modifié l'objet tuple; nous avions un tuple que nous avons converti en objet liste, modifié l'objet liste puis créé un nouvel objet tuple.
Le tuple est très utilisé pour une opération qu'on appelle le **tuple unpacking**. Vous avez dans un tuple deux variables, ''a'' et ''b'', et vous dites que ces variables sont égales à une séquence qui doit avoir le même nombre d'éléments que le nombre d'éléments que vous avez dans votre tuple. Par exemple, je vais mettre une liste ''[3, 4]''. Après execution de ce code on s'aperçoit que la variable ''a'' référence l'entier 3, ma variable ''b'' référence l'entier 4.
# tuple unpacking
>>> (a, b) = [3,4]
>>> print(a)
3
>>> print(b)
4
On a mentionné plus haut que dans le tuple on pouvait enlever les parenthèses. Une des raisons, c'est justement pour alléger cette notation;
# tuple unpacking notation naturelle allégée
>>> a, b = [3,4]
Cette notation fonctionne parfaitement, ce sont deux tuples mais on a enlevé les parenthèses pour alléger la notation, et on voit bien que maintenant ''a'' vaut bien 3, et ''b'' vaut bien 4.
En Python, il existe également la notion de **extended tuple unpacking**. C'est une manière simple de pouvoir isoler des éléments à partir d'un grand nombre d'éléments dans une séquence.
# extended tuple unpacking
# ici le premier élément de la liste est associé a la variable x
# tous les autres sont associés à la seconde variable y
>>> (x, y*) = list( range(10) )
>>> type(x)
int
>>> print(x)
0
>>>type(y)
list
>>>print(y)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Dans cet exemple à droite de l'égalité, on définit une liste contenant 10 éléments des entiers allant de 0 jusqu'à 9 (c'est notre longue séquence). Maintenant, supposons que l'on veuille prendre uniquement le premier élément, et les autres éléments dans un autre objet. Nous pouvons l' obtenir grâce à la notation présentée dans l'exemple ci-dessus. "x" est égal au premier élément et "y" va référencer une liste contenant tous les éléments restants. Vous pouvez bien évidemment utiliser la notation dans l'autre sens par exemple, faire %%*x, y%% pour obtenir un autre tuple unpacking dans lequel vous allez isoler uniquement le dernier élément. Dans ce cas "x" référencera la liste de 0 à 8, et "y" uniquement 9.
===== Résumé =====
Nous avons présenté le tuple. Le tuple est un objet séquence **très proche de la liste, dont la principale différence est d'être immuable**. Le tuple est utilisé notamment dans des opérations de **tuple unpacking**, comme nous venons de le voir, mais également par exemple, comme **clé de dictionnaire**.