UKOnline

Variable et type de donnée

On souhaite parfois conserver en mémoire le résultat de l'évaluation d'une expression arithmétique en vue de l'utiliser plus tard, dans un autre calcul, par exemple. Si on reprend l'exemple de la recherche des racines du trinôme $ax^2 + bx + c$, on doit mémoriser la valeur du discriminant pour pouvoir calculer les valeurs des deux racines réelles distinctes, lorsqu'il est strictement positif.

Variable

Une variable peut être vue comme une boite (virtuelle) représentant un emplacement en mémoire qui permet de stocker une valeur, et à qui on a donné un nom afin de facilement l'identifier. La figure 4 illustre ce concept en montrant une variable dont le nom est data et dont la valeur est le nombre entier $42$.

Variable
Une variable est une boite virtuelle, représentant un emplacement mémoire, qui possède un nom et une valeur.

Voyons maintenant un exemple de programme qui utilise plusieurs variables pour calculer le discriminant du trinôme $x^2 + 2x - 4$ :

Les trois premières instructions stockent les coefficients du trinôme, à savoir $1$, $2$ et $-4$, respectivement dans des variables nommées a, b et c. La quatrième instruction effectue le calcul du discriminant ($b^2 - 4ac$) et stocke le résultat dans la variable delta. Enfin, les deux dernières instructions affichent à l'écran la phrase «Le discriminant est :», suivie de la valeur de la variable delta.

L'utilisation d'une variable est donc assez immédiate. Deux types d'accès peuvent être réalisés :

  • Pour affecter une valeur à une variable, c'est-à-dire l'initialiser ou modifier sa valeur, on utilise l'opérateur d'affectation (=). À gauche de l'opérateur on retrouve le nom de la variable et à droite la valeur qu'on souhaite lui affecter.
  • Pour accéder au contenu d'une variable, il suffit d'utiliser son nom. Cet accès peut, par exemple, se faire dans une expression mathématique, ou avec la fonction print.

Le symbole = est à distinguer du signe égal utilisé en mathématiques pour énoncer une égalité. En Python, il permet d'affecter une valeur à une variable. Voyons cela avec l'exemple suivant :

En mathématiques, écrire $b = a$ signifie que $a$ et $b$ représentent la même valeur. Dès lors, lorsqu'on écrit plus loin a = 15, on pourrait s'attendre à ce que $a$ et $b$ valent $15$. En Python, b = a signifie qu'on affecte la valeur de a à la variable b (on fait une copie de la valeur). Après exécution de cette instruction, aucun lien n'est établi entre les deux variables. L'exécution du programme affiche lors de son exécution :

1
1
15
1

La figure 5 illustre ce qui se passe en mémoire. Elle montre l'état de cette dernière respectivement juste après l'exécution des instructions a = 1, b = a et a = 15. On voit très bien qu'aucun lien n'a été établi entre les variables a et b et que la dernière modification de a n'a aucun impact sur la valeur de b.

Opérateur d'affectation
L'opérateur d'affectation permet d'affecter une valeur à une variable. Elle n'établit aucun lien entre deux variables comme on peut le voir avec l'état de la mémoire respectivement après exécution des instructions a = 1, b = a et a = 15.

Initialisation de variable

Avant de pouvoir accéder au contenu d'une variable, il faut qu'elle soit initialisée, c'est-à-dire qu'elle doit posséder une valeur. Si vous tentez d'utiliser une variable non initialisée, l'exécution du programme va s'arrêter et l'interpréteur Python va produire une erreur d'exécution. Voyons cela avec l'exemple de programme suivant :

Le programmeur a fait une malencontreuse faute de frappe à la troisième instruction, et lors de son exécution, l'interpréteur s'arrête et produit une erreur :

Sa taille est :
Traceback (most recent call last):
  File "program.py", line 3, in <module>
    print(heigth)
NameError: name 'heigth' is not defined

L'avant dernière ligne reprend l'instruction qui a causé l'erreur d'exécution (à savoir print(heigth) dans notre cas). La dernière ligne fournit une explication sur la cause de l'erreur (celle qui commence par NameError). Dans cet exemple, elle indique que le nom heigth n'est pas défini, c'est-à-dire qu'il ne correspond pas à une variable initialisée.

Modification de variable

Une fois une variable initialisée, on peut donc modifier sa valeur en utilisant de nouveau l'opérateur d'affectation (=). La valeur actuelle de la variable est remplacée par la nouvelle valeur qu'on lui affecte. Dans l'exemple suivant, on initialise une variable à la valeur $12$ et on remplace ensuite sa valeur par $99$ :

On voit bien sur le résultat de l'exécution que la valeur de la variable data a été remplacée par $99$ et qu'il n'y a plus aucune trace du $12$ :

99

Affectation composée

Ce que l'on doit parfois faire, c'est mettre à jour une variable par rapport à la valeur qu'elle possède actuellement. Par exemple, si on veut augmenter la valeur d'une variable data de $1$, on doit écrire :

La nouvelle valeur à affecter à la variable data est sa valeur actuelle à qui on ajoute $1$. Dans cette instruction, le nom de la variable est répété deux fois. En programmation, une règle de bonne pratique consiste à éviter au maximum la duplication de code. Pour simplifier cette instruction, Python propose l'opérateur += qui fait l'addition suivie de l'affectation en une fois. L'exemple précédent se réécrit donc comme suit :

Un tel opérateur permet de réaliser une affectation composée, c'est-à-dire une opération directement suivie d'une affectation. On peut notamment l'utiliser avec les sept opérateurs arithmétiques que l'on vient de voir.

Type de donnée

Un programme passe une grande partie de son temps à manipuler des données. On a déjà pu voir plusieurs types de données différents dans les sections précédentes, à savoir des nombres et des mots. Il existe de nombreux types prédéfinis en Python, parmi lesquels les nombres et les chaines de caractères.

Nombre

Il y a trois types numériques en Python :

  • Le type entier (int) permet de représenter n'importe quel nombre entier, peu importe sa taille.
  • Le type flottant (float) permet de représenter des nombres comportant une partie décimale, compris entre $10^{-308}$ et $10^{308}$. La valeur spéciale math.inf représente l'infini.
  • Le type complexe (complex) permet de représenter des nombres complexes, où le nombre imaginaire se note j.

Il y a deux manières d'introduire de telles données dans un programme. On peut directement écrire le nombre, qu'on appellera littéral entier. On obtient également des données numériques à partir d'expressions mathématiques et de fonctions prédéfinies. Deux points d'attention sont à soulever concernant l'écriture littérale de nombres :

  • On utilise le point comme séparateur décimal lorsqu'on doit écrire des nombres à virgule.
  • On colle directement la partie imaginaire d'un nombre complexe au j sans utiliser un *. En effet, 2j représente le nombre complexe $2i$ tandis que 2 * j représente le produit de $2$ par la variable j.

Comme le montre l'exemple suivant, les flottants peuvent être écrits en notation scientifique. Il s'agit d'un programme qui calcule les deux racines complexes d'un trinôme du second degré :

La première instruction importe la fonction prédéfinie sqrt depuis le module cmath, afin de calculer la racine carrée d'un nombre complexe. On initialise ensuite trois variables a, b et c avec des données numériques décrites par un littéral ($1$, $-4$ et $2\cdot10^2$). La cinquième instruction calcule le discriminant qui sera un nombre flottant ($\Delta = b^2 - 4ac$).

Les deux instructions suivantes calculent les racines du trinôme, en faisant notamment appel à la fonction sqrt pour calculer $x_{1,2} = (-b \pm \sqrt{\Delta}) / 2a$. Les variables x1 et x2 vont donc contenir des données de type complexe. Comme on peut le voir sur ce qu'affiche l'exécution du programme, c'est bien le cas :

Les deux racines sont :
(2+14j)
(2-14j)

Chaine de caractères

Une chaine de caractères (str) est une séquence de caractères, délimitée par des guillemets dans sa forme littérale (simple ' ou double "). On peut généralement utiliser indifféremment l'un ou l'autre type de guillemets.

Tous les caractères, à quelques exceptions près, sont acceptés pour définir une chaine de caractères. Tout d'abord, il est évident que si vous souhaitez utiliser le caractère ", vous ne pourrez pas l'utiliser pour délimiter la chaine de caractères, mais vous devrez utiliser ', et inversement.

Dans l'exemple suivant, on est obligé d'utiliser des guillemets doubles pour délimiter la chaine de caractères :

Si on veut créer des chaines de caractères contenant à la fois ' et ", il faut utiliser une séquence d'échappement. Une telle séquence commence par un backslash (\) suivi d'un ou plusieurs caractères. Elle permet de représenter un caractère spécial. Par exemple, la séquence \" représente le caractère " et la séquence \n représente un saut de ligne. On peut par exemple écrire :

L'exécution de ce programme affiche deux lignes de texte à l'écran, la séquence d'échappement \n ayant été remplacée par un saut de ligne :

Promenade de l'Alma 50
1200 Woluwé-Saint-Lambert

La figure 6 ci-dessous reprend les principales séquences d'échappement que propose Python.

Séquence Description
\\ Backslash
\' Guillemet simple (apostrophe)
\" Guillemet double
\n Saut de ligne
\r Retour chariot
\t Tabulation horizontale
Les séquences d'échappement permettent d'insérer des caractères spéciaux dans une chaine de caractères.

Il faut faire bien attention à distinguer les deux littéraux 123 et '123'. Alors que le premier est de type numérique et représente le nombre entier $123$, le second est une chaine de caractères constituée des trois caractères 1, 2 et 3, placés l'un après l'autre.

On peut s'en rendre compte grâce à la fonction prédéfinie type qui permet d'obtenir le type d'une expression. On voit, sur l'exemple suivant, les mentions <class 'int'> et <class 'str'> qui indiquent respectivement le type numérique entier et le type chaine de caractères :

>>> type(123)
<class 'int'>
>>> type('123')
<class 'str'>

On peut connaitre la longueur d'une chaine de caractères (c'est-à-dire le nombre de caractères qui la composent) en utilisant la fonction prédéfinie len. Enfin, on peut joindre deux chaines de caractères l'une derrière l'autre avec l'opérateur de concaténation (+). Dans l'exemple suivant, la variable s contiendra Hello World! après exécution :

Attention, cet opérateur ne fonctionne qu'entre deux données de type chaine de caractères. Si vous tentez de l'utiliser avec un autre type, l'interpréteur Python produira une erreur d'exécution.

Le programme suivant initialise une variable de type entier contenant l'année actuelle et définit ensuite une variable s à laquelle on tente d'affecter la concaténation de la chaine de caractères 'Nous sommes en ' avec la variable de type entier year :

L'interpréteur Python va générer une erreur d'exécution qui signale qu'il ne parvient pas à convertir implicitement la donnée de type int en une donnée de type str :

Traceback (most recent call last):
  File "program.py", line 2, in <module>
    s = 'Nous sommes en ' + year
TypeError: Can't convert 'int' object to str implicitly

Conversion

Il est possible de convertir explicitement une donnée d'un type vers un autre, en utilisant des fonctions prédéfinies. Les fonctions int, float, complex et str permettent de convertir une donnée vers les types correspondants. Voyons un premier exemple :

La variable a est de type numérique entier. On la convertit ensuite en une donnée de type complexe grâce à la fonction prédéfinie complex, et on stocke le résultat de la conversion dans la variable b. Ceci est confirmé par l'exécution du programme qui affiche :

<class 'int'>
<class 'complex'>

Grâce à ces fonctions de conversion, on peut maintenant corriger l'exemple de la section précédente. Il suffit en effet d'appliquer la fonction str à la variable year avant d'effectuer la concaténation :

Toutes les conversions ne fonctionnent évidemment pas. Si on tente, par exemple, de convertir une chaine de caractères en un entier, mais qu'elle ne représente pas un nombre entier, on aura une erreur d'exécution :

Le message d'erreur obtenu signale que la chaine de caractères 'Hello' n'est pas un entier valable en base 10 :

Traceback (most recent call last):
  File "program.py", line 1, in <module>
    a = int("Hello")
ValueError: invalid literal for int() with base 10: 'Hello'