Aller au contenu

Langages et programmation

Introduction

Qu'est-ce qu'un programme ?

Un programme informatique est un ensemble d'opĂ©rations destinĂ©es Ă  ĂȘtre exĂ©cutĂ©es par un ordinateur. À la diffĂ©rence d'un algorithme, il est en gĂ©nĂ©ral Ă©crit dans un langage de programmation.

Qu'est-ce qu'un langage de programmation ?

C'est un langage "facilement" comprĂ©hensible par un ĂȘtre humain et qui peut ĂȘtre "traduit" dans le langage machine qui est difficilement manipulable par un humain. Comme n'importe quel langage, un langage de programmation possĂšde des symboles, une grammaire, une orthographe, on parle de syntaxe.

Il existe des centaines de langage de programmation : par exemple Javascript, les langages C et C++, Java, Lisp, OCaml, PHP, Smalltalk, Ruby, etc.

Les langages peuvent sembler trÚs différents mais ils partagent tous des structures communes. Le langage que nous utiliserons principalement dans ce cours sera Python, cependant l'objectif de ce cours n'est pas d'apprendre le langage Python en particulier, mais d'insister sur les bases qu'ils partagent avec les autres langages.

On n'apprend pas "un langage de programmation", on apprend Ă  programmer.

Remarque

Dans la suite du cours, nous utiliserons systÚmatiquement >>> pour représenter une console interprétant Python, le résultat étant affiché à la ligne en dessous, comme dans l'exemple ci-contre:

⚙ RĂ©sultat
>>> 3 + 7    
10

ÉlĂ©ments de base d'un programme

Notion d'expression

Une expression est un texte qui peut ĂȘtre Ă©valuĂ© par l'interprĂ©teur Python, c’est Ă  dire que que chaque expression possĂšde une valeur que l’on peut obtenir par un calcul.

  • 7 est une expression simple, le rĂ©sultat de son Ă©valuation est 7

    ⚙ RĂ©sultat
    >>> 7
    7
    
  • 3 + 4 est une expression composĂ©e, le rĂ©sultat de son Ă©valuation est 7.

    ⚙ RĂ©sultat
    >>> 3 + 4
    7
    
  • on appelle la fonction max avec les arguments 3 et 4

    ⚙ RĂ©sultat
    >>> max(3, 4)
    4
    
  • on peut crĂ©er des expressions arbitrairement complexes

    ⚙ RĂ©sultat
    >>> 2 + max(3 + 4, 4)
    9
    

Commentaire

Les commentaires sont des portions du code source ignorĂ©es par la machine car destinĂ©es en gĂ©nĂ©ral Ă  un lecteur humain pour permettre d’expliquer le code. En Python, le reste d’une ligne suivant un # est un commentaire.

⚙ RĂ©sultat
>>> # Cette expression ne fait strictement rien

Notion de type

Un aspect essentiel des langages de programmation est la notion de type. Tout objet manipulĂ© par Python en possĂšde un, qui caractĂ©rise la maniĂšre dont il est reprĂ©sentĂ© dans la mĂ©moire de l’ordinateur, et dont vont dĂ©pendre les opĂ©rations et fonctions qu’on peut lui appliquer.

La fonction type permet de connaĂźtre le type d’un objet. Par exemple, le type int est utilisĂ© pour reprĂ©senter les nombres entiers (nĂ©gatifs et positifs), le type str pour les chaĂźnes de caractĂšres :

⚙ RĂ©sultat
>>> type (2)
<class ’int ’>
>>> type(" Bonjour ")
<class ’str ’>

Les types sont importants pour dĂ©finir les opĂ©rations que l’on peut appliquer aux objets, par exemple :

⚙ RĂ©sultat
>>> 7 + " Bonjour "
Traceback (most recent call last):
File "<stdin >", line 1, in <module >
TypeError : unsupported operand type(s) for +: ’int ’ and ’str ’

L’interprĂ©teur nous signale qu’il n’est pas possible d’additionner un objet de type int et une chaĂźne de caractĂšre de type str.

Python possÚde également un type float, pour les nombres décimaux. Le nom float vient de la dénomination nombre à virgule flottante sur laquelle nous reviendront plus tard.

On remarque que la « virgule » se note avec un point (comme sur la calculatrice) et qu’il est possible d’additonner un Ă©lĂ©ment de type int avec un type float.

⚙ RĂ©sultat
>>> type (4.25)
<class ’float ’>
>>> type (2.0)
<class ’float ’>
>>> 4.5 + 3
7.5

Attention, une fois entre guillemet un nombre n’est plus du type int ou float mais devient une chaüne de caractùre.

⚙ RĂ©sultat
>>> type("42")
<class ’str ’>

On peut parfois convertir un type en un autre, par exemple :

⚙ RĂ©sultat
>>> type(int("42")) # La fonction int permet d'effectuer la conversion
<class ’int ’>

Opérateurs arithmétiques

Le langage Python fournit les opérateurs mathématiques classiques

  • Addition, soustraction

    ⚙ RĂ©sultat
    >>> 2 + 3
    5
    >>> 2 - 3
    -1
    
  • Multiplication, division

    ⚙ RĂ©sultat
    >>> 3 * 5
    15
    >>> 15 / 2
    7.5
    
  • Mise Ă  la puissance

    ⚙ RĂ©sultat
    >>> 2 ** 5 # 2 puissance 5
    32
    
  • Quotient dans la division euclidienne

    ⚙ RĂ©sultat
    >>> 15 // 2 # 15 divisé par 2 donne 7 reste 1
    7
    
  • Reste dans la division euclidienne

    ⚙ RĂ©sultat
    >>> 15 % 2 # 15 divisé par 2 donne 7 reste 1
    1
    

Fonctions

Définir une fonction

Considérons le problÚme suivant :

« Calculer le pĂ©rimĂštre d’un rectangle dĂ©fini par sa largeur et sa longueur. »

La solution mathĂ©matique est d’appliquer dans chacun des cas la formule $2 \times (\text{longueur } + \text{ largeur})$, en fonction des dimensions du rectangle. Par exemple en Python :

⚙ RĂ©sultat
>>> 2 * (4 + 3) # rectangle de longueur 4 et de largeur 3
14
>>> 2 * (7 + 5) # rectangle de longueur 7 et de largeur 5
24

On peut définir une fonction perimetre qui prend en argument deux nombres longueur et largeur et qui renvoie le périmÚtre d'un rectangle ayant pour dimensions longueur $\times$ largeur.

🐍 Code Python
1
2
3
4
5
6
def perimetre(longueur, largeur):
    """ int, int -> int
    precondition : (longueur > 0) et (largeur > 0)
    Renvoie le pĂ©rimĂštre d'un rectangle de dimensions longueur × largeur
    """
    return 2 * (longueur + largeur)

On peut à présent appeler la fonction perimetre :

⚙ RĂ©sultat
>>> perimetre(4, 3)
14

>>> perimetre(7, 5)
24

Spécification

L’objectif de la spĂ©cification d’une fonction est de permettre de dĂ©finir explicitement son comportement, de comprendre ce qu’elle fait et quelles sont ses restrictions.

La fonction Python help permet d’obtenir la spĂ©cification d’une fonction :

⚙ RĂ©sultat
>>> help(perimetre)    
perimetre(longueur, largeur)
    int, int -> int
    precondition : (longueur > 0) et (largeur > 0)
    Renvoie le pĂ©rimĂštre d'un rectangle de dimensions longueur × largeur

La spĂ©cification d’une fonction peut se dĂ©composer en quatre parties :

  • l’en-tĂȘte qui prĂ©cise le nom de la fonction et de ses paramĂštres (on dit aussi de ses arguments) ;
  • la signature qui prĂ©cise le type de ses paramĂštres et de sa valeur de retour ;
  • d’éventuelles prĂ©conditions qui fixent les restrictions sur les paramĂštres ;
  • la description du rĂŽle de la fonction.

Tests

Pour dĂ©tecter d’éventuelles erreurs, les fonctions sont accompagnĂ©es d’un jeu de tests. On utilise pour cela l’instruction assert.

⚙ RĂ©sultat
assert perimetre(4, 3) == 14
assert perimetre(7, 5) == 24
assert perimetre(2, 2) == 8

Si perimetre(4, 3) ne renvoie pas la valeur attendue 14, un message d’erreur apparaitra. Par exemple

⚙ RĂ©sultat
>>> assert perimetre(4, 3) == 42 # la valeur de test est incorrecte
Traceback (most recent call last):
File "<stdin>", line 1, in <module >
AssertionError

Création d'une fonction

L'utilisation de fonctions est fondamentale en informatique. Cela permet notamment de réutiliser des portions de codes utiles. Pour cela on ajoute un niveau d'intation au code en question, et on ajoute la spécification de la fonction. Par exemple :

🐍 Code Python
1
2
3
4
5
6
from turtle import *

# dessine un carré de cÎté 80
for i in range(4):
    forward(80)
    left(90)
🐍 Code Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from turtle import *

def carre(cote):
    """ int -> None
    Dessine un carré de cÎté cote
    """
    for i in range(4):
        forward(cote)
        left(90)
    return None

BibliothĂšques de fonctiosn

Les fonctions les plus utiles sont souvent déjà écrites en Python. Nous pouvons en utiliser certaines directement, comme : max, help, type ou print.

D’autres sont aussi disponibles dans des bibliothùques de fonctions (en anglais librairies ou module). Par exemple :

  • math (qui contient toutes les fonctions mathĂ©matiques courantes) ;
  • random (qui contient des fonctions qui renvoient des nombres pseudo-alĂ©atoires).

Pour pouvoir utiliser les fonctions présents dans ces bibliothÚques, on doit importer la bibliothÚque. Par exemple, pour obtenir un nombre au hasard entre 0 et 10 (inclus).

⚙ RĂ©sultat
>>> import random # import de la bibliothĂšque
>>> random.randint(0, 10) # appel de la fonction randint du module random
7

On peut également importer une fonction d'une bibliothÚque spécifique. Par exemple, la fonction sqrt du module math calcule la racine carrée d'un nombre flottant.

⚙ RĂ©sultat
>>> from math import sqrt
>>> sqrt(2)
1.4142135623730951

Remarque. L'instruction from turtle import * importe toutes les fonctions du module turtle. C'est une mauvaise pratique dans le cas général.

Variables et affectation

Quand on exécute un programme, la machine nous attribue une plage de mémoire dans laquelle nous pouvons stocker des données. Cette mémoire est constituée de "cases", toutes identifiées par une adresse.

Une variable peut ĂȘtre vue comme un nom que l'on donne Ă  une valeur stockĂ©e en mĂ©moire. On peut utiliser les variables pour stocker ou modifier une information en mĂ©moire.

Lorsque l'on donne une valeur $v$ à une variable ma_variable, on écrit en pseudo-code $\texttt{ma_variable} \leftarrow v$. L'instruction Python correspondante est ma_variable = v.

On dit que l'on affecte Ă  ma_variable la valeur $v$.

Si ma_variable possÚde déjà une valeur, la nouvelle valeur écrase la précédente.

Remarque. En Python, le nom d’une variable ou d’une fonction est une suite de lettres (minuscules ou majuscules) et de chiffres, qui doit toujours commencer par une lettre, et qui ne contient pas de caractĂšres spĂ©ciaux sauf l’underscore : _. Il n’est pas possible d’utiliser des mots clefs du langage, tel que def ou for.

Il est d’usage de choisir des termes explicites pour faciliter la lecture du code. Nous Ă©viterons les majuscules et les accents pour les noms de variables ou de fonction, nous utiliserons _ pour sĂ©parer les mots.

Noms de variable

Barrer avec une croix les noms de variables qui sont invalides. Rayer d'un trait les noms de variable qui sont mals choisis.

hello "world" for en−tete Ă©tat 6_nbre
six nbr nbr Dromadaire monChameau mon_python attention!
def _largeur_ 42      

Affectation de $1$ Ă  la variable a

⚙ RĂ©sultat
>>> a = 1
>>> a
1

On peut modifier le contenu d'une variable Ă  l'aide de plusieurs affectations.

⚙ RĂ©sultat
>>> a = 1
>>> a = 2
>>> a
2

On peut copier le contenu d'une variable dans une autre.

⚙ RĂ©sultat
>>> a = 1
>>> b = a
>>> b
1

Les variables peuvent ĂȘtre utilisĂ©es dans des expressions.

⚙ RĂ©sultat
>>> l = 4
>>> L = 3
>>> p = 2*(l + L)
>>> p
14

Il est possible de réaliser des affectations multiples.

⚙ RĂ©sultat
>>> a, b, c = 1, 2, "NSI"
>>> b
2

La fonction id renvoie un nombre entier qui reprĂ©sente la case mĂ©moire oĂč est stockĂ©e l'information relative Ă  la variable.

⚙ RĂ©sultat
>>> a = 1
>>> id(a)
140344818602800

Important. L'affectation copie la valeur de l'expression Ă  droite du signe = dans la case mĂ©moire identifiĂ©e par le nom Ă  gauche du signe =. La valeur de la variable peut-ĂȘtre modifiĂ©e Ă  un autre endroit du programme.

⚙ RĂ©sultat
>>> a = 1
>>> c = a + 1
>>> a = 42
>>> c
2

Ainsi, le signe = en Python ne traduit pas une égalité mathématique entre objets.

Conditions et instructions conditionnelle

Une condition est une expression qui s'évalue à True (la condition est vraie) ou False (la condition est fausse). On dit que les conditions sont de type booléen.

Les conditions portent sur les variables en mémoire. En pseudo code on utilise les symboles mathématiques. En Python on utilise les symboles suivants :

\renewcommand{\arraystretch}{1.5}

Tester si Code python
x est Ă©gal Ă  y  
x est diffĂ©rent de y  
x est infĂ©rieur Ă  y  
x est supĂ©rieur ou Ă©gal Ă  y  
x \(\in\) \([\texttt{a}, \texttt{b}]\)  

On peut combiner des conditions entre elles à l'aide des opérateurs and, or et not.

On peut comparer des nombres entre eux :

⚙ RĂ©sultat
>>> 3 + 7 < 5
False

On peut affecter le résultat d'une expression à une variable

⚙ RĂ©sultat
>>> condition = 3 + 7 < 5
>>> condition
False

On peut exprimer des conditions complexes :

⚙ RĂ©sultat
x < 0 or x > 100          # False si x appartient Ă  [0 ; 100]
0 <= y and y <= 100       # True si y appartient Ă  [0 ; 100]
0 <= z <= 100             # True si z appartient Ă  [0 ; 100]
not (x < 0)               # False si x < 0

Il est souvent nécessaire de n'exécuter des instructions que dans certains cas. Dans ce cas on utilise une structure conditionnelle.

Par exemple, on dispose des instructions instruction1, instruction2, instruction3, instruction4, et instruction5 et de conditions condition1, condition2 et condition3.

🐍 Code Python
1
2
3
4
5
instruction1
if condition1:
    instruction2
    instruction3
instruction4
🐍 Code Python
1
2
3
4
5
6
7
if condition1:
    instruction1
    instruction2
else:
    instruction3
    instruction4
instruction5
🐍 Code Python
1
2
3
4
5
6
7
8
9
if condition1:
    instruction1
elif condition2:
    instruction2
elif condition3:
    instruction3
else:
    instruction4
instruction5

On remarque un décalage vers la droite à l'écriture des instructions. C'est ce que l'on appelle l'indentation. Il sert à structurer le code. L'annulation de l'indentation marque la sortie de la structure conditionnelle.

🐍 Code Python
1
2
3
4
x = -4
if x > 0:
    print("positif")
print("fin")
⚙ RĂ©sultat
fin
🐍 Code Python
1
2
3
4
5
6
x = -4
if x < 0:
    print("négatif")
else:
    print("positif ou nul")
print("fin")
⚙ RĂ©sultat
négatif
fin
🐍 Code Python
1
2
3
4
5
6
7
8
9
temperature = 21
if temperature < 0:
    print("gel")
elif temperature < 15:
    print("froid")
elif temperature < 30:
    print("bon")
else:
    print("chaud")
⚙ RĂ©sultat
bon

Boucles

Boucles bornées

Lorsque l'on souhaite répéter un bloc d'instruction un nombre de fois connu à l'avance, on utilise une boucle bornée, aussi appelée boucle for ("pour").

🐍 Code Python
1
2
for <variable> in range(<nombre répétitions>):
    <bloc d'instructions à répéter>

Par exemple :

🐍 Code Python
1
2
3
4
# Affiche "NSI <3" 5 fois de suite
for i in range(5):
    # i est la variable de boucle
    print("NSI <3")
🐍 Code Python
1
2
3
# Affiche 9 16 25 
for i in range(3, 6):
    print(i**2)  # on peut utiliser la variable de boucle dans le bloc d'instructions
🐍 Code Python
1
2
3
for i in range(3):
    for j in range(4):
        print(j)
🐍 Code Python
1
2
3
4
s = 0
for i in range(101):
    s = s + i
print(s) # affiche le résultat de 0 + 0 + 1 + 2 + 3 + ... + 100
🐍 Code Python
1
2
3
4
5
6
7
8
9
def mult(a, b):
    """ int, int -> int
    Additionnne b fois le nombre a """
    s = 0
    for i in range(b):
        s = s + a
    return s

assert mult(3, 5) == 15

Remarque. On peut utiliser différentes syntaxes pour la boucle for :

for i in range(n): i prend successivement pour valeurs 0, 1, \ldots, n - 1
for i in range(n, m): i prend successivement pour valeurs n, n + 1, \ldots, m - 1
for i in range(n, m, p): i prend successivement pour valeurs n, n + p, n + 2p, \ldots
for i in a, b, c, d: i prend successivement pour valeurs a, b, c, puis d
🐍 Code Python
1
2
for i in range(3):
    print(i, end = ' ')
⚙ RĂ©sultat
0 1 2
🐍 Code Python
1
2
for i in range(2, 5):
    print(i, end = ' ')
⚙ RĂ©sultat
2 3 4
🐍 Code Python
1
2
for i in range(2, 15, 4):
    print(i, end = ' ')
⚙ RĂ©sultat
2 6 10 14
🐍 Code Python
1
2
for i in range(5, -1, -1):
    print(i, end = ' ')
⚙ RĂ©sultat
5 4 3 2 1 0

Boucles non bornées

Il arrive parfois que l'on souhaite répéter un bloc d'instruction un nombre de fois qui n'est pas connu à l'avance. Pour cela, on utilise une boucle non bornée, aussi appelée boucle while ("tant que").

🐍 Code Python
1
2
while <condition>:
    <bloc d'instructions à répéter>

On souhaite déterminer le plus petit nombre entier $n$ tel que $2^n$ soit plus grand qu'un certain nombre flottant nbr fixé à l'avance. On calcule les différentes puissances de $2$ : $2^0$, $2^1$, $2^2$, $2^3$, \ldots tant que celles-ci sont plus petites que nbr.

🐍 Code Python
1
2
3
4
5
6
7
8
def plus_petit_entier(nbr):
    """ float -> int
    nbr > 0
    Détermine l'exposant de la plus petite puissance de 2 >= n """
    exposant = 0
    while 2**exposant < nbr:
        exposant = exposant + 1
    return exposant

On dresse la trace d'exécution de plus_petit_entier(10) :

Ligne exĂ©cutĂ©e l3.                        
nbr                          
exposant                          
2**exposant < nbr                          

Attention. Si la condition de la boucle est toujours vraie, alors les instructions sont rĂ©pĂ©tĂ©es sans jamais s'arrĂȘter. On parle de "boucle infinie".

🐍 Code Python
1
2
3
while 2 == 1 + 1:
    print("Et tourne tourne tourne la galĂšre")
print("Ouf c'est fini !")

Il est toujours possible de transformer une boucle for en une boucle while. Cependant, le contraire n'est pas toujours vrai.

Par exemple, les deux programmes ci-dessous produisent le mĂȘme affichage.

🐍 Code Python
1
2
for i in range(5):
    print(i)
🐍 Code Python
1
2
3
4
i = 0
while i < 5:
    print(i)
    i = i + 1

Il n'est par contre pas possible de transformer la boucle while de la fonction plus_petit_entier en boucle for.

Lorsque l'on peut se passer d'une boucle while, on préfÚre toujours écrire un programme à l'aide d'une boucle for.