Python est un langage de programmation interprété développé par Guido van Rossum en 1989. Langage impératif de haut-niveau doté d’une syntaxe simple, Python s’adapte à de nombreux contextes grâce à sa modularité ; une importante librairie de modules et packages permet en effet d’étendre ses capacités.
Python possède son propre shell (interface en ligne de commande) : l’utilisateur entre une commande Python qui est interprétée immédiatement lorsque Entrée
est tapée.
Au lancement, le shell Python, poli, se présente :
Python 3.7.3 (default, Mar 27 2019, 16:54:48)
[Clang 4.0.1 (tags/RELEASE_401/final)] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
Les 3 chevrons sont l’invite (ou prompt) où les commandes seront écrites.
IPython, un shell plus évolué, utilise [1]
comme invite (où le chiffre dans les crochets s’incrémente à chaque commande).
Pour sortir du shell classique, il faut taper exit()
, et exit
ou quit
pour sortie du shell IPython.
On peut tout à fait exécuter des commandes Python une à une dans le shell.
Une commande qui renvoie un résultat est appelée expression, alors qu’une commande qui ne renvoie rien est une instruction.
Toute fonction est une expression, mais certaines ont en plus un effet sur l’environnement comme print()
qui permet d’afficher une chaîne de caractères dans le shell ou dans un fichier (elle retourne aussi la valeur None
qui est omise dans ce cas par le shell).
5 + 2
7
a = 7
print(a)
7
Pour les projets plus complexes nécessitant d’enchaîner les instructions, on écrit l’ensemble de ces commandes (le programme) dans un éditeur de texte et on enregistre le fichier avec une extension .py
.
On demande alors à l’interprète Python d’exécuter l’ensemble du script en utilisant la commande python nom_du_fichier.py
dans le shell de l’OS. Les différents retours dans le shell ne sont alors plus affichés, seuls les effets ont un… effet.
Le plus simple pour coder est d’utiliser un environnement de travail (IDE pour “integrated development environment”) qui combine un éditeur de code et un shell Python permettant d’exécuter le script entier ou une partie directement via l’interface.
Cela fait parti du bon usage en informatique de commenter son code afin qu’il soit plus facilement compréhensible et donc partageable. En Python, les commentaires sont placés derrière un hastag #
les rendant invisible pour l’interprète.
import math # pour pouvoir utiliser pi (commentaire ignoré par l'interprète)
r = 3 # rayon
2*math.pi*r # circonférence du cercle de rayon r
L’installation d’Anaconda rend disponible les principales bibliothèques scientifiques Python ainsi que le preformant IDE Spyder ou encore Jupyterlab (très intéressant pour les présentations de projets car associant dans une même interface texte et code pour former un notebook).
Les oraux de Centrale “Mathématiques 2” et “Physique-chimie 2” utilisent l’IDE Pyzo. Les ordinateurs du lycée ont les IDE EduPython et Pyzo disponibles sur le serveur S:\
. Vous pouvez aussi utiliser pour dépanner l’IDE en ligne Repl.it depuis le repository du TP.
Les nombres sont parmi les objets Python les plus basiques.
Il en existe 3 types :
int
).float
).complex
).4+3j
(la partie imaginaire est notée j
en python).4+3j
peut aussi s’écrire complex(4,3)
.Taper un nombre dans le shell Python renvoie simplement la nombre :
5
5
5.
5.0
0.10
0.1
0.0001
0.0001
0.0000999
9.99e-05
Les nombres inférieurs à 0,0001 sont écrits en notation scientifique.
On peut changer le type d’un nombre (conversion) en utilisant les fonctions natives int()
, float
et complex
:
float(5)
5.0
int(5.2)
5
int(5.9)
5
On remarque que la transformation en entier d’un nombre décimal prend en fait sa partie entière.
complex(3.)
(3+0j)
complex(0.,3.)
3j
Les opérateurs de base utilisables en Python sont :
symbole | opération |
---|---|
+ |
addition |
- |
soustraction |
* |
multiplication |
/ |
division décimale |
// |
division euclidienne |
% |
modulo (reste de la division euclidienne) |
** |
puissance |
Règles de priorités des opérations :
**
> { *
,/
, //
, %
} > { +
, -
}
6 / 2 / 4 # comme 3 / 4
0.75
6 / (2 / 4) # comme 6 / 0.5
12.0
2**2**3 # comme 2**(2**3) == 2**8
256
(2**2)**3 # comme 4**3
64
Les opérations de priorité égale sont évaluées de gauche à droite à l’exception des puissances (ce qui correspond à évaluer de haut en bas les exposants).
En Python, tout, y compris un nombre, est un objet ayant certains attributs accessibles grâce à la notation “point” : <objet>.<attribut>
.
Certains attributs sont des simples valeurs : les nombres complexes ont par exemple les attributs real
et imag
qui sont les parties réelles et imaginaires d’un nombre complexe.
(3+4j).imag
4.0
D’autres attributs sont des méthodes : des fonctions qui modifient leur objet d’une façon ou d’une autre.
Par exemple, les nombres complexes ont la méthode conjugate
qui retourne le complexe conjugué :
(3+4j).conjugate()
(3-4j)
round
et abs
sont deux fonctions proposées par défaut (natives).
abs
retourne la valeur absolue d’un nombre entier ou décimal, ou le module d’un nombre complexe (c’est un exemple de polymorphisme : comportement différent en fonction du type de l’argument).
abs(-7.2)
7.2
abs(3+4j)
5.0
round
arrondi un nombre décimal à l’entier le plus proche (attention, la convention utilisée lorsque la décimale vaut 5 est l’arrondi bancaire ou arrondi au pair le plus proche : au-dessus lorsque la partie entière est impaire et en dessous lorsqu’elle est paire).
round(7.6)
8
round(7.5)
8
round(8.5)
8
Python est un langage d’une grande modularité : des fonctionnalités supplémentaires sont accessibles en important des modules ou des packages qui ne sont pas chargés par défaut (ce qui permet de ne pas encombrer la mémoire).
Beaucoup de fonctions mathématiques utiles peuvent ainsi être ajoutées grâce au module math
, importé grâce à la déclaration import math
.
import math
math.exp(-1.5)
0.22313016014842982
math.cos(0)
1.0
math.sqrt(9)
3.0
L’ensemble des fonctions disponibles dans le module sont répertoriées dans sa documentation en ligne et les plus utiles sont dans le tableau suivant (les angles des fonctions trigonométriques sont supposés en radians) :
nom de la fonction | signification | nom de la fonction | signification |
---|---|---|---|
math.sqrt(x) |
$$\sqrt{x}$$ | math.atan(x) |
$$\arctan (x)$$ |
math.exp(x) |
$$e^x$$ | math.sinh(x) |
$$\sinh (x)$$ |
math.log(x) |
$$\ln (x)$$ | math.cosh(x) |
$$\cosh (x)$$ |
math.log(x,b) |
$$\log_b(x)$$ | math.tanh(x) |
$$\tanh (x)$$ |
math.log10(x) |
$$\log_{10}(x)$$ | math.asinh(x) |
$$\text{arsinh} (x)$$ |
math.sin(x) |
$$\sin (x)$$ | math.acosh(x) |
$$\text{arcosh} (x)$$ |
math.cos(x) |
$$\cos (x)$$ | math.atanh(x) |
$$\text{artanh} (x)$$ |
math.tan(x) |
$$\tan (x)$$ | math.hypot(x,y) |
norme euclidienne $$\sqrt{x^2+y^2}$$ |
math.asin(x) |
$$\arcsin (x)$$ | math.degrees(x) |
convertit x des radians aux degrés |
math.acos(x) |
$$\arccos (x)$$ | math.radians(x) |
convertit x des degrés aux radians |
Le module math
propose aussi deux attributs très utiles : math.pi et math.e qui donnent les valeurs de $\pi$ et $e$.
Il est possible d’importer le module math
par la commande from math import *
afin d’accéder à ses fonctions directement :
from math import *
cos(pi)
-1.0
Bien que cela puisse être pratique pour des petites interactions avec le shell, ce n’est pas recommandé pour des programmes plus conséquent car cela peut générer confusions et conflits de noms.
On peut bien sûr composer les fonctions :
math.degrees(math.acos(math.sqrt(3)/2))
30.000000000000004
Notons que le nombre affiché diffère du résultat exact attendu $\arccos(\sqrt{3}/2)=30°$. C’est dû au codage machine des flottants qui ne permet qu’une précision limité.
Lorsqu’un objet, comme un float
, est créé dans un programme Python, une certaine place en mémoire lui est allouée. Cette place est repérée par une adresse dont la valeur peut être obtenue grâce à la fonction id()
.
id(3.7)
4387417928
Il est beaucoup plus pratique de pouvoir récupérer une valeur en mémoire grâce à un petit nom plutôt que par son adresse. C’est à ça que servent les variables. Une variable est liée à un objet grâce à une affectation et identifie cet objet pour les calculs suivants.
a = 3
b = -0.1
a * b
-0.30000000000000004
À nouveau, le résultat décimal affiché est un peu étrange, toujours à cause de la précision limité des flottants (environ 16 chiffres significatifs seulement)…
Si on veut pouvoir utiliser le résultat de a * b
pour des calculs ultérieurs, il faut lui aussi le stocker en mémoire.
c = a * b
c
-0.30000000000000004
Contrairement à des langages à typage statique comme le C, le type d’une variable n’a pas besoin d’être déclarée en Python. On parle alors de typage dynamique. Mais il faut néanmoins initialiser la valeur de la variable pour ne pas provoquer d’erreur. Le type de la variable est induit au moment de cette première affectation.
3+x
NameError: name 'x' is not defined
On peut interroger le type d’une variable avec la fonction type()
:
type(c)
float
Règles sur les noms de variables :
and
assert
break
class
continue
def
del
elif
else
except
finally
for
from
global
if
import
in
is
lambda
nonlocal
not
or
pass
print
raise
return
try
while
yield
Il est important pour la lisibilité de son code de donner les noms les plus explicites possibles aux variables. Les rapports de jury le répète tous les ans…
Rapport 2019 de l’épreuve de Centrale par exemple :
Des noms de variables explicites aident à la compréhension du code. De trop nombreux candidats utilisent des noms de variables quelconques (a, b, c…) ce qui nuit à la compréhension du programme. La clarté du programme (en particulier le choix des noms de variables) ainsi que la présence de commentaires opportuns sont prises en compte dans l’évaluation.
Une affectation ne retourne rien (c’est une instruction) mais a un effet sur la mémoire : l’adresse de la variable est modifiée à chaque nouvelle affectation. C’est ce qui rend possible les réaffectations à partir de la variable elle-même.
id(a)
4304751488
id(a+1)
4304751520
a = a + 1
id(a)
4304751520
Ces types de réaffectation sont si fréquents qu’il existe une notation raccourcie : +=
, -=
, *=
, /=
, //=
, %=
.
Ainsi, a += 1
équivaut à a = a + 1
et b /= 5
équivaut à b = b/5
.
Python permet d’affecter plusieurs variables simultanément (en parallèle) :
a , b = 3.2 , -2
a
3.2
b
-2
Comment faire si on veut permuter les valeurs auxquelles sont liées deux variables ? Dès qu’on écrit a = b
, la valeur initiale de a
est perdue. Et si on commence par b = a
, c’est la valeur initiale de b
qui est perdue. Il faudrait donc utiliser une variable temporaire et écrire : tmp = a
, a = b
et b = tmp
.
Mais l’affectation parallèle de Python va nous permettre d’être plus élégants. Il suffit en effet d’une petite ligne :
a , b = b , a
print(a,b)
-2 3.2
L’affectation parallèle repose sur le packing et l’unpacking de tuples, mais on verra ça dans un prochain cours.
Les différents comparateurs utilisables en Python sont :
comparateur | signification |
---|---|
== |
égal à |
!= |
différent de |
> |
supérieur à |
< |
inférieur à |
>= |
supérieur ou égal à |
<= |
inférieur ou égal à |
Le résultat d’une comparaison est un objet booléen (type bool
) qui a deux valeurs possibles : True
ou False
.
7 == 8
False
4 >= 3.8
True
a = 4 < 3
type(a)
bool
Il faut bien noter la différence entre =
qui affecte une valeur à une variable et ==
qui compare deux valeurs.
La précision finie des nombres flottants rend leur comparaison dangereuse :
a , b = 0.01 , 0.1**2
a == b
False
En effet :
a
0.01
b
0.010000000000000002
Les comparaisons peuvent être modifiées et enchaînées grâce aux opérateurs logiques and
(et), or
(ou inclusif), et not
(non).
7.0 > 4 and -1 >= 0
False
5 < 4 or 1 != 0
True
Dans des expressions composées comme celles-ci, les opérateurs de comparaison sont évalués en premier puis vient le tour des opérateurs logiques.
not 7.5 < 0.9 or 4 == 4
True
not (7.5 < 0.9 or 4 == 4)
False
Un nombre entier ou décimal peut être considéré comme un booléen dans des expressions logiques. Dans ce cas, tout nombre différent de zéro est considéré comme vrai.
18.7 and 5 < 8
True
On parle d’égalité de valeurs (testée par l’opérateur ==
) lorsque deux variables référencent la même valeur et d’égalité physique lorsqu’il s’agit du même objet ayant un emplacement mémoire unique. L’égalité physique implique bien sûr l’égalité de valeurs.
Pour tester l’égalité physique de deux variables, on utilise l’opérateur is
.
a = 257
b = 257
a == b
True
a is b
False
a is 257
False
id(a)
4396188400
id(b)
4396188144
id(257)
4396188272
c = 256
d = 256
c is d
True
c is 256
True
id(c)
4304759584
id(d)
4304759584
id(256)
4304759584
Python garde en cache les petits entiers (de -5 à 256 généralement), souvent utilisés, pour améliorer les performances. a
et b
sont alors tout deux liés à l’espace mémoire de l’objet 256
. Ils correspondent donc bien au même objet physique.
None
Enfin, pour nous aider à traiter les cas où aucune valeur définie n’est possible (soit parceque la valeur conduirait à une erreur où n’aurait pas de sens), Python propose d’utiliser la valeur None
de type NoneType
.
C’est particulièrement utile pour éviter des valeurs par défaut arbitraireS comme 0
ou -99
pour des données manquantes ou corrompues.
On en verra un exemple d’utilisation dans le TP 3.