Aller au contenu

Définir un tuple

Directement

On a déjà vu comment définir un tuple de façon directe en écrivant son contenu:

>>> a = (2, 3, 4)
>>> a
(2, 3, 4)

Pour définir un tuple ne contenant qu'un seul élément, on n'oubliera pas de le faire suivre d'une virgule:

>>> a = (2,)
>>> a
(2,)
>>> type(a)
<class 'tuple'>
>>> b = (2)
>>> b
2
>>> type(b)
<class 'int'>

Par concaténation

On peut également construire un nouveau tuple à l'aide de tuples déjà définis par concaténation:

>>> a = ("bonjour", "tout")
>>> b = ("le", "monde")
>>> c = a + b
>>> c
('bonjour', 'tout', 'le', 'monde')

Immuable

Attention, un tuple est immuable: après sa définition, il n'est pas possible de modifier un tuple.

Si vous essayez par exemple de redéfinir l'élément d'indice 2 par une affectation a[2] = 42, vous obtiendrez une erreur.

>>> a = (2, 3, 4)
>>> a
(2, 3, 4)
>>> a[2] = 42
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

Immuabilité et affectation

Avec le code suivant:

>>> a = (2, 3)
>>> a =  a + (4, 5)
>>> a
(2, 3, 4, 5)

on ne modifie pas le tuple initial (2, 3) en le tuple (2, 3, 4, 5).

Ligne 1:

  • On construit d'abord l'objet (2, 3).
  • Puis on attribue l'étiquette a à cet objet (une affectation se lit toujours de droite à gauche: on construit l'objet qui se trouve à droite, puis on lui attribue l'étiquette qui se trouve à gauche).

Ligne 2:

  • On concatène (2, 3) et (4, 5). Ce qui crée le nouvel objet (2, 3, 4, 5).
  • Puis on lui attribue l'étiquette a.
Rappel

Une instruction d'affectation, par exemple:

a =  a + (4, 5)

s'exécute toujours de droite à gauche. On construit d'abord l'objet défini dans la partie droite de l'affectation. Puis on colle l'étiquette qui est située à gauche de = sur l'objet construit. En particulier, à gauche de =, il ne peut y avoir que des noms de variables (des "étiquettes"), il ne peut pas y avoir de calcul dans la partie gauche.

Ainsi, on peut avoir l'impression d'avoir modifié le contenu de a. Mais ce n'est pas ainsi qu'il faut penser ce qu'il se passe: l'étiquette a désignait un premier objet à la fin de la ligne 1, puis l'étiquette a désigne un nouvel objet en fin de ligne 2.

En python, chaque objet a un identifiant (que l'on peut voir comme son emplacement en mémoire) obtenu avec la fonction id:

>>> a = (2, 3)
>>> id(a)
140491492586824
>>> a = a + (3, 4)
>>> id(a)
140491492598072

L'instruction id(a) renvoie l'identifiant de l'objet étiqueté a: on voit que a ne désigne pas le même objet en ligne 2 et en ligne 5 (l'objet étiqueté n'est pas stocké au même emplacement mémoire en machine).

Exercice 1

Définir une fonction python spécifiée comme suit:

def puissance2(n):
    """
    n -- entier > 0

    renvoie le tuple (2**0, 2**1, 2**2, ..., 2**n)
    """
Un code
def puissance2(n):
    """
    n -- entier > 0

    renvoie le tuple (2**0, 2**1, 2**2, ..., 2**n)
    """
    a = (1,)
    for i in range(1, n+1):
        a = a + (2**i,)
    return a

Remarque.

Si l'on préfère (sur le modèle de ce que l'on a déjà fait avec des sommes de nombres ou des constructions de chaînes de caractères) commencer par un tuple vide, on utilisera tuple() pour définir ce tuple vide:

def puissance2(n):
    """
    n -- entier >= 0

    renvoie le tuple (2**0, 2**1, 2**2, ..., 2**n)
    """
    a = tuple()
    for i in range(0, n+1):
        a = a + (2**i,)
    return a
Utiliser ce code

Rappelons comment utiliser (tester) la fonction définie.

  • Si l'on écrit le code de cette fonction dans un fichier a.py, on peut l'appeler depuis l'interpréteur python. Ouvrir une console:
$ python3
Python 3.7.1 (default, Dec 14 2018, 19:28:38) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from a import puissance2
>>> puissance2(4)
(1, 2, 4, 8, 16)
  • On peut aussi dans le fichier a.py ajouter une ligne telle que:
print(puissance2(4))

puis exécuter le fichier (par exemple en tapant python3 a.py en console).

Un autre code possible

Nous verrons comment générer des listes par compréhension dans le chapitre sur les listes. Générer le tuple demandé dans cet exercice par compréhension s'écrirait comme suit:

def puissance2(n):
    """
    n -- entier > 0

    renvoie le tuple (2**0, 2**1, 2**2, ..., 2**n)
    """
    return tuple(2**i for i in range(n+1))

Exercice 2

Après la dernière ligne ci-dessous, quelles sont les valeurs des objets dont les étiquettes respectives sont a et b ?

>>> a = (2, 3)
>>> b = a
>>> a = a + (5, 6)

Essayez de répondre d'abord sans tester.

Réponse

On teste:

>>> a = (2, 3)
>>> b = a
>>> a = a + (5, 6)
>>> a
(2, 3, 5, 6)
>>> b
(2, 3)

En dernière ligne, l'étiquette a ne désigne plus l'objet (2, 3) mais l'objet (2, 3, 5, 6) du fait de la ligne 3.

En ligne 2, l'affectation b = a signifie que l'on colle une seconde étiquette sur l'objet ayant déjà l'étiquette a.

L'étiquette a est "décollée" de l'objet (2, 3) pour être recollée sur un autre objet. Mais l'étiquette b, elle, est restée collée sur le même objet.

On peut lire ainsi les diverses affectations:

>>> Colle l'étiquette a sur le pot de confiture contenant (2, 3)
>>> Colle l'étiquette b sur le pot de confiture ayant l'étiquette a
>>> Remplit un pot de confiture avec (2, 3) + (5, 6), 
décolle l'étiquette a de son pot actuel
et colle cette étiquette sur notre nouveau pot.