LANGAGE PYTHON : TYPES DE DONNEES
CONSTRUITS

Guido van Rossum créateur du langage Python est né 1956 à Amsterdam. Il effectue des études de mathématiques dans sa ville natale et obtient un master en 1982. Il travaille alors en tant que développeur dans la conception du langage ABC dont il s'inspire pour élaborer le langage Python en 1991.

## 1 – INTRODUCTION¶

Les types de données simples vus précédemment tels que `int` (nombres entiers), `float` (nombres flottants), `bool` (booléens) ou `str` (chaîne de caractères) ne sont plus suffisants s'il est nécessaire de traiter un grand nombre de valeurs ou pour le regroupement de valeurs de types différents.

Les types de variable construits est un type de variable capable de contenir plusieurs valeurs de même ou de types différents. Il existe trois sortes de types construits :

- les p-uplets (type `tuple`) ;
- les tableaux (type `list`) ;
- les dictionnaires (type `dict`).

## 2 – LES N-UPLETS OU TUPLES¶

### 2.1 – Type Tuple¶

Un n-uplet est un objet de type tuple. Il s'agit d'une suite ordonnée d’éléments qui peuvent être de types différents : entiers, flottants, chaînes de caractères voir d’autres tuples. On parlera indifféremment de n-uplet ou de tuple.

Un objet `t` de type tuple n’est pas modifiable par une affectation `t[i]=valeur`. On dit qu'il s'agit d'un type non mutable.

### 2.2 – Création d'un tuple¶

Voici quelques exemples de création de tuples :

In [1]:

    t1 = ('a',)      # tuple à 1 élément
    t1

Out[1]:

    ('a',)

In [2]:

    t2 = ('a', 2, 'b', 1.5)  # tuple à 4 éléments
    t2

Out[2]:

    ('a', 2, 'b', 1.5)

In [3]:

    t3 = ()                  # tuple à 0 élément
    t3

Out[3]:

    ()

Bien que préconisées, il possible de créer un tuple sans utiliser les parathèses hormis pour les tuples vides pour lesquels les parenthèses sont obligatoires.

In [4]:

    t4 = 'a',                # tuple à 1 élément
    t4

Out[4]:

    ('a',)

In [ ]:

    t5 = 'a', 2, 'b', 1.5    # tuple à 4 éléments
    t5

> Exercice 1 :

> 1. Executer le script suivant et vérifier que les tuples ont été correctement crées.

In [5]:

    t1 = ('a',)
    t2 = ('a', 2, 'b', 1.5)
    t3 = ()
    print(t1)
    print(t2)
    print(t3)

    ('a',)
    ('a', 2, 'b', 1.5)
    ()

> 2. Vérifier le type des 3 variables créees ci-dessus à l'aide de la fonction `type`.

In [9]:

    type(t3)

Out[9]:

    tuple

> 3. Exécuter le script suivant et justifier l'erreur de l'exécution.

In [12]:

    t3 = (0,4,"a")
    print(t3[2])

    a

> Réponse :

Il est possible de créer un tuple contenant un autre tuple :

In [13]:

    t4 = ('a', 'b', (1, 2))   # tuple à 3 éléments dont le troisième est un tuple
    t4

Out[13]:

    ('a', 'b', (1, 2))

### 2.3 – Opérations sur les tuples¶

Comme les chaînes de caractères, les tuples supportent les opérations de concaténation `+` et de répétition `*`.

In [ ]:

    t5 = (1, 'a')
    t6 = (2, 'b')

In [ ]:

    t5 + t6     # Concaténation

In [ ]:

    4 * t5      # Répétition

### 2.4 – Appartenance¶

Pour tester l’appartenance d’un élément à un tuple, on utilise l’opérateur `in`. Cet opérateur renvoie `True` si l'élément appartient au tuple, sinon il retourne `False`.

In [ ]:

    t7 = ('a', 'b', 'c')

In [ ]:

    'a' in t7

In [ ]:

    'd' in t7

### 2.5 – Accès aux éléments¶

Pour un tuple non vide, les `n` élements sont indéxés (numérotés) de `0 à n-1`. L'indice du premier élément est `0`. L'indice du dernier élément est `n-1`.

La fonction `len` permet de connaître la longueur d'un tuple.

In [ ]:

    t8 = ('a', 1, 'b', 2, 'c', 3)

In [ ]:

    len(t8)

Pour accéder à un élément d’un tuple, il faut utiliser la notation `t[i]` :

In [ ]:

    t8[0]

In [ ]:

    t8[5]

Il est également possible d'accéder à plusieurs éléments à la fois pour cela on utilise la notation `t[i:j]`

In [ ]:

    t8[2:4]

Il est également possible d'accéder à un éléments à partir du dernier élément également noté -1.

In [ ]:

    t8[-1]

In [ ]:

    t8[-4]

Pour accéder à un élément d'un tuple contenu dans un tuple, il faut utiliser la notation à double indice `t[i][j]`.

In [ ]:

    t9 = (('a', 'b'), ('c', 'd'))

In [ ]:

    t9[0][1]

> Exercice 2 :

> Exécuter le script suivant et justifier l'erreur de l'exécution.

In [ ]:

    t9 = (('a', 'b'), ('c', 'd'))
    print(t9[0][2])

> Réponse :

### 2.6 – Affectations multiples de variables¶

Les éléments d'un tuple ne sont pas modifiables (non mutables) par une affectation du type `t[i]=valeur`. Une telle affectation entraîne une erreur.

In [ ]:

    t10 = (1, 2, 3, "bonjour")

In [ ]:

    t10[3] = 'au revoir'

Il possible d'utiliser un tuple pour affecter des valeurs, de manière simultanée, à différentes variables. Par exemple affectation de valeurs obtenues par l'execution d'une fonction renvoyant un tuple.

In [ ]:

    (a, b, c, d) = t10

In [ ]:

    a

In [ ]:

    d

> Exercice 3 :

> 1. Editer la fonction `division(a, b)` qui retourne le quotient et le reste obtenus par la division euclidienne de `a` par `b`.

In [ ]:

    def divivion(a, b):
        # A compléter

> 2. Tester la fonction en affectant aux variables `x` et `y` le résultat retourné par la fonction.

In [ ]:

    x, y = division(25, 7)
    print(x, y)

## 3 – TABLEAUX¶

### 3.1 – Tableau Python¶

Un tableau permet de stocker plusieurs variables dans une seule variable et d'y accéder ensuite facilement. En python on construit un tableau en énumérant ses valeurs entre crochets et séparées par des virgules. Il s'agit d'une suite ordonnée d’éléments modifiable par une affectation `T[i]=valeur`. On dit qu'un tableau est mutable.

Remarque : Sous python, les tableaux sont appelés listes. Il s'agit d'objets de type `list`. Ils différent des tableaux utilisés dans les autres langages par le fait qu'ils peuvent être agrandis ou rétrécis du côté droit ce qui les distingue des tableaux usuels dont la taille est fixée une fois pour toute lors de la création.

Dans la suite du cours nous utiliserons le terme tableau pour parler des objets listes.

### 3.2 – Création d'un tableau¶

Les éléments d'un tableau sont séparés par des virgules et entourés de crochets.

In [ ]:

    tab1 = [1, 2, 3, 4]   # Tableau contenant 4 entiers
    tab1

In [ ]:

    tab2 = ["Paul", "Charles", "Jacques"]   # Tableau contenant 3 chaînes de caractères
    tab2

In [ ]:

    tab3 = [[1, 2], [3, 4], [5, 6]]         # Tableau contenant 3 tableau : tableau à deux dimensions
    tab3

In [ ]:

    tab4 = [1]   # Tableau contenant un élément
    tab4

In [ ]:

    tab5 = []     # Tableau vide
    tab5

### 3.3 – Fonction list¶

La fonction `list` associée à la fonction `range` permet de créer des tableaux notamment de grandes tailles.

In [ ]:

    tab6 = list(range(4))   # permet de créer le tableau [0, 1, 2, 3]
    tab6

In [ ]:

    tab7 = list(range(3, 6))   # permet de créer la tableau [3, 4, 5]
    tab7

In [ ]:

    tab8 = list(range(1, 10, 2))   # permet de créer la tableau [1, 2, 5, 7, 9]
    tab8

> Exercice 4 :

> Créer un tableau `tab9` contenant les 20 premiers nombres pairs positifs.

In [ ]:

    tab9 =
    tab9

### 3.4 – Construction par compréhension¶

Pour créer une liste par compréhension il faut utiliser la syntaxe suivante : `[expression(i) for i in objet]`

Par exemple, le code ci-dessous permet de créer un tableau pairs à partir d'un tableau nombres.

In [ ]:

    nombres = [1, 2, 3, 4, 5]
    pairs = [2*n for n in nombres]
    pairs

Il est possible d'utiliser une fonction pour réaliser `expression(i)`.

    def f(x) :                          # Ne pas exécuter
        return ....

    tableau1 = .....
    tableau2 = [f(x) for x in tableau1]

Par exemple :

In [ ]:

    def f(x) :
        y = x**2 - 3*x + 2
        return y
    tableau1 = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5]
    tableau2 = [f(x) for x in tableau1]
    tableau2

> Exercice 5 :

> Créer un tableau `tab10` contenant le carré des 10 premiers nombres pairs positifs.

In [ ]:

    tab10 =
    tab10

### 3.5 – Accès aux éléments¶

Si un tableau est non vide, ses `n` élements sont indéxés (numérotés) de `0 à n-1`. L'indice du premier élément est `0`. L'indice du dernier élément est `n-1`.

La fonction `len` retourne la taille d'un tableau c'est-à-dire le nombre d'éléments qu'il contient.

In [ ]:

    tab11 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    len(tab11)

L'accès aux élements d'un tableau est réalisé comme pour les tuples.

In [ ]:

    tab11[0]       # Accès à un éléments

In [ ]:

    tab11[2:6]     # Accès à plusieurs éléments

In [ ]:

    tab11[-1]       # Accès au dernier élément

In [ ]:

    tab11[-5]       # Accès à un élement à partir du dernier

In [ ]:

    tab12 = [[1, 2], [3, 4], [5, 6]]
    tab12[2][1]     # Accès à un élement d'un tableau à 2 dimensions

Contrairement aux objets de type tuple, il est possible de modifier un élément d'un tableau par affectation. Les tableaux sont des objets mutables.

In [ ]:

    tab13 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    tab13[0] = 0
    tab13

La fonction `del` permet de supprimer l'élément repéré par l'indice mais l'élement est perdu.

In [ ]:

    del(tab13[5])
    tab13

### 3.6 – Méthodes¶

Pour ajouter un élément en fin d'un tableau, il est possible d'utiliser la méthode `append` :

In [ ]:

    tab15 = ["Paul", "Charles", "Jacques"]

In [ ]:

    tab15.append("Robert")
    tab15

Pour ajouter un élément à un endroit précis, on utilise la méthode `insert(y, x)` qui ajoute l'élément `x` à l'index `y`.

In [ ]:

    tab15.insert(2, "Gilbert")
    tab15

Il existe deux méthodes pour supprimer un élément. La méthode `pop` et la méthode `remove`.

Si l'élément est connu, il faut utiliser la methode `remove`.

In [ ]:

    tab15.remove("Charles")
    tab15

La méthode `remove(x)` supprime le premier élement `x` rencontré en parcourant le tableau depuis le début

In [ ]:

    tab16 = ["Paul", "Charles", "Jacques"]
    tab16.append("Charles")
    tab16

In [ ]:

    tab16.remove("Charles")
    tab16

L'instruction `remove("Charles")` a supprimé le prémier élément `"Charles"` rencontré.

Si l'indice est connu, la methode `pop` supprime et retourne l'élément repéré par l'indice.

In [ ]:

    tab16 = ["Paul", "Charles", "Jacques"]
    nom = tab16.pop(1)
    nom, tab16

Si aucune valeur n'est transmise à la methode `pop`, celle-ci supprime et retourne le dernier élément du tableau.

In [ ]:

    tab16 = ["Paul", "Charles", "Jacques"]
    nom = tab16.pop()
    nom, tab16

La méthode `count` permet d'obtenir le nombre d'occurence d'un élement dans un tableau.

In [ ]:

    tab17 = ["Paul", "Charles", "Jacques", "Charles", "Robert"]
    nbr = tab17.count("Charles")
    nbr

La méthode `reverse` permet d'inverser l'ordre des éléments d'un tableau.

In [ ]:

    tab18 = [1, 10, 2, 9, 3, 8, 4, 7, 5, 6]
    tab18.reverse()
    tab18

La méthode `sort` permet de trier les éléments d'un tableau.

In [ ]:

    tab18.sort()
    tab18

### 3.7 – Opérations sur les tableaux¶

Comme les chaînes de caractères et les tuples, les tableaux supportent les opérations de concaténation `+` et de répétition `*`.

In [ ]:

    tab19 = [1, 2, 3]
    tab20 = [4, 5]
    tab19 + tab20

In [ ]:

    3 * tab19

### 3.8 – Appartenance¶

Pour tester l’appartenance d’un élément à un tableau, on utilise l’opérateur `in`. Cet opérateur renvoie `True` si l'élément appartient au tableau, sinon il retourne `False`.

In [ ]:

    tab19 = [1, 2, 3]
    1 in tab19

In [ ]:

    5 in tab19

### 3.9 – Copie d'un tableau¶

En python, toutes les données (nombres, chaînes de caractères, listes ...) sont des objets. Lors d'une affection, le nom de la variable n'est qu'une référence vers un objet.

In [ ]:

    a = 2

Dans l'affectation précédente `a` n'est rien d'autre qu'un nom qui fait référence à un objet de type `int`. Ce mode d'affectation demande une grande vigilance car il peut entraîner des comportements non désirés. Considérons les lignes de code suivantes :

    tableau1 = [1, 2, 3]
    tableau2 = tableau1
    tableau2[1] = 4

> Exercice 6 :

> 1. Donner les valeurs attendues pour les tableaux `tableau1` et `tableau2`.

> Réponse :

> 2. Exécuter les lignes de code ci-dessous pour vérifier la réponse à la question précédente.
> 3. Cliquer "Vizualise Execution" puis sur "Forward" pour éxécuter les lignes de code une à une.

In [ ]:

    from tutor import tutor
    tableau1 = [1, 2, 3]
    tableau2 = tableau1
    tableau2[1] = 4
    tutor()

Pour obtenir une véritable copie d'un tableau, c'est-à-dire créer un nouvel objet, il faut utiliser la fonction `list` ou la méthode `copy`.

    Tableau1 = [1, 2, 3]
    Tableau2 = list(Tableau1)
    Tableau2[1] = 4

> Exercice 7 :

> Exécuter les lignes de code ci-dessous pour pour visualiser le fonctionnement de la fonction `copy`.

In [ ]:

    from tutor import tutor
    Tableau1 = [1, 2, 3]
    Tableau2 =Tableau1.copy()
    Tableau2[1] = 4
    tutor()

Considérons la méthode `copy` dans le cas de d'un tableau contenant des tableaux :

> Exercice 8 :

> Exécuter les lignes de code ci-dessous pour visualiser le fonctionnement du programme et justifier pourquoi les deux tableaux ont été modifiées.

In [ ]:

    from tutor import tutor
    Tableau1 = [[1, 1], [2, 2], [3, 3]]
    Tableau2 = Tableau1.copy()
    Tableau2[0][1] = 4
    print(Tableau2)
    print(Tableau1)
    tutor()

Dans le cas de tableaux contenant des tableaux il faut utiliser la fonction `deepcopy` (copie profonde).

> Exercice 9 :

> Exécuter les lignes de code ci-dessous pour visualiser le fonctionnement de la fonction `deepcopy`.

In [ ]:

    from copy import deepcopy
    Tableau1 = [[1, 1], [2, 2], [3, 3]]
    Tableau2 = deepcopy(Tableau1)
    Tableau2[0][1] = 4
    print(Tableau2)
    print(Tableau1)

### 3.9 - Parcours d'un tableau¶

Un tableau est un objet itérable, c'est-à-dire qu'il possible de parcourir le tableau et d'avoir accès aux différents éléments à l'aide d'une boucle `for`.

In [ ]:

    Somme = 0
    t20 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    for n in t20:
        Somme = Somme + n
    Somme

Il possible de parcourir le tableau à partir des indices de chaque élément.

In [ ]:

    Somme = 0
    t20 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    for i in range(len(t20)):  # i va prendre la valeur 0 à len(t20)-1 c'est-à-dire 9
        Somme = Somme + t20[i] # accès aux élements à partir de l'indice
    Somme

## 4 – DICTIONNAIRES¶

### 4.1 – Type dictionnaire¶

Un dictionnaire est un objet de type `dict`. Un dictionnaire permet de stocker des données sous la forme `(clé : valeur)`. Une clé est unique et peut être du type entier, flottant, chaîne de caractères ou tuple.

In [ ]:

    d1 = {"Math": 14, "Anglais": 12.5, "Français": 13}
    d1

### 4.2 – Création d'un dictionnaire¶

Création d'un dictionnaire, à l'aide de la fonction `dict`, à partir d'une liste ou d'un couple de valeurs de la forme `cle = valeur`.

In [ ]:

    liste = [["Math", 14 ], ["Anglais", 12.5], ["Français", 13], ["Physique", 11] ]
    d2 = dict(liste)
    d2

In [ ]:

    d3 = dict(Histoire = 8, EPS = 18, NSI = 20)
    d3

Il est également possible de créer un dictionnaire par compréhension.

In [ ]:

    d4 = {'a' + str(x) : x**2 for x in range(1, 5)}
    d4

### 4.3 – Accès aux éléments¶

Comme pour les tuples et les tableaux, La fonction `len` retourne la taille d'un dictionnaire.

In [ ]:

    d5 = {"Math": 14, "Anglais": 12.5, "Français": 13, "Physique": 11}
    len(d5)

Les méthodes `keys` et `values` permettent d'accéder aux clés et aux valeurs d'un dictionnaire.

In [ ]:

    d6 = {"Math": 14, "Anglais": 12.5, "Français": 13, "Physique": 11}

In [ ]:

    d6.keys()

In [ ]:

    d6.values()

La méthode `items` donne accès à l'ensemble des couples.

In [ ]:

    d6.items()

Il est possible d'accéder à une valeur à partir de sa clé.

In [ ]:

    d6["Anglais"]

Les dictionnaires sont, comme les tableaus, des objets mutables, c'est-à-dire qu'il est possible de modifier un élément de la manière suivante `d[cle]=valeur`.

In [ ]:

    d7 = {"Math": 14, "Anglais": 12.5, "Français": 13, "Physique": 11}
    d7["Anglais"] = 15
    d7

Si on essaie d'obtenir une valeur à partir d'un clé qui n'existe pas, le programme provoque une erreur.

In [ ]:

    d8 = {"Math": 14, "Anglais": 12.5, "Français": 13, "Physique": 11}
    Note = d8["EPS"]
    Note

La méthode `get` permet de retourner la valeur d'un élément à partir d'une clé existante et retourne `None` si la clé n'existe pas.

In [ ]:

    d8 = {"Math": 14, "Anglais": 12.5, "Français": 13, "Physique": 11}
    Note = d8.get("Math")
    Note

In [ ]:

    Note = d8.get("EPS")
    print(Note)

Si la clé n'existe pas, la méthode `get` permet de créer un couple `(clé: valeur)` en initialisant `valeur`.

In [ ]:

    d8 = {"Math": 14, "Anglais": 12.5, "Français": 13, "Physique": 11}
    d8["EPS"] = d8.get("EPS", 15)
    d8

### 4.5 – Opérations sur les dictionnaires¶

L'opérateur `&` permet de retourner les clés communes à deux dictionnaires.

In [ ]:

    d9 = {"Paul": 18, "Léa": 18, "Kévin": 19, "Cloé": 17}
    d10 = {"Nathan": 17, "Clara": 16, "Kévin": 19, "Jeanne": 17}
    d9.keys() & d10.keys()

L'opérateur `&` permet également de retourner les couples `(clé: valeurs)` communs à deux dictionnaires.

In [ ]:

    d9.items() & d10.items()

L'opérateur `-` (moins) permet de retourner les éléments qui sont présents dans un dictionnaire et pas dans l'autre.

In [ ]:

    d9 = {"Paul": 18, "Léa": 18, "Kévin": 19, "Cloé": 17}
    d10 = {"Nathan": 17, "Clara": 16, "Kévin": 19, "Jeanne": 17}
    d9.keys() - d10.keys()

In [ ]:

    d9.items() - d10.items()

Pour effacer un élement du dictionnaire il faut utiliser la fonction `del` en indiquant la clé de l'élèment à effacer.

In [ ]:

    d9 = {"Paul": 18, "Léa": 18, "Kévin": 19, "Cloé": 17}
    del(d9["Paul"])
    d9

La méthode `clear` permet d'effacer tout un dictionnaire.

In [ ]:

    d9 = {"Paul": 18, "Léa": 18, "Kévin": 19, "Cloé": 17}
    d9.clear()
    d9

### 4.5 – Appartenance¶

L’opérateur `in` permet de tester si une clé appartient au dictionnaire. Cet opérateur ne fonctionne pas sur les valeurs. Cet opérateur renvoie `True` si la clé appartient au dictionnaire, sinon il retourne `False`.

In [ ]:

    d8 = {"Math": 14, "Anglais": 12.5, "Français": 13, "Physique": 11}
    "Math" in d8

In [ ]:

    d8 = {"Math": 14, "Anglais": 12.5, "Français": 13, "Physique": 11}
    'EPS' in d8

### 4.6 – Copie d'un dictionnaire¶

Le comportement lors des affectations d'un dictionnaire est équivalent à celui des tableaux.

> Exercice 10 :

> Exécuter sur les instructions ci-dessous pour voir le mécanisme d'affection dans le cas de dictionnaires.

In [ ]:

    from tutor import tutor
    paul = {"Math": 14, "Anglais": 12.5, "Français": 13, "Physique": 11}
    pierre = paul
    pierre["Math"] = 12
    print("Pierre : ", pierre)
    print("Paul : ", paul)
    tutor()

Pour remédier à ce problème, il est possible de copier un dictionnaire dans un nouvel objet dict en utilisant les fonctions `dict` ou `copy` comme pour les tableaux.

In [ ]:

    paul = {"Math": 14, "Anglais": 12.5, "Français": 13, "Physique": 11}
    pierre = dict(paul)
    pierre["Math"] = 12
    print("Pierre : ",pierre)
    print("Paul : ",paul)

In [ ]:

    paul = {"Math": 14, "Anglais": 12.5, "Français": 13, "Physique": 11}
    pierre = Paul.copy()
    pierre["Anglais"] = 16
    print("Pierre : ", pierre)
    print("Paul : ", paul)

Considérons la méthode `copy` dans le cas de dictionnaires contenant des listes :

> Exercice 11 :

> Exécuter les lignes de codes ci-dessous pour voir le mécanisme d'affection dans le cas de dictionnaires contenant des tableaux.

In [ ]:

    from tutor import tutor
    d12 = {'a': [1, 1], 'b': [1,2], 'c': [1,3]}
    d13 = d12.copy()
    d13['a'][1] = 0
    print("d13 = ", d13)
    print("d12 = ", d12)
    tutor()

Dans le cas de dictionnaires contenant des tableaux il faut utiliser la fonction `deepcopy` (copie profonde) du module `copy`.

> Exercice 12 :

> Exécuter les lignes de code ci-dessous pour visualiser le fonctionnement de la fonction `deepcopy`.

In [ ]:

    from copy import deepcopy
    d12 = {'a': [1, 1], 'b': [1,2], 'c': [1,3]}
    d13 = deepcopy(d12)
    d13['a'][1] = 0
    print("d13 = ", d13)
    print("d12 = ", d12)

### 4.6 - Parcours d'un dictionnaire¶

Comme les tableaux, le dictionnaire est un objet itérable, c'est-à-dire qu'il possible de parcourir le dictionnaire à l'aide d'une boucle `for`. Le dictionnaire peut parcouru à partir des clés ou des couples `(clé: valeur)`.

In [ ]:

    notes = {"Math": 14, "Anglais": 12.5, "Français": 13, "Physique": 11}
    for cle in notes.keys():
        print("Matière : ", cle, " : ", notes[cle])

In [ ]:

    notes = {"Math": 14, "Anglais": 12.5, "Français": 13, "Physique": 11}
    for cle, valeur in notes.items():
        print("Matière : ", cle, " : ", valeur)

In [ ]: