Initiation à Python

Compléments

Booléens

Il existe deux constantes True et False (avec majuscule !), avec les opérateurs infixes and, or et l’opérateur préfixe not qui ne nécessite pas de parenthèses par défaut. L’opérateur d’égalité se note avec == et celui de différence avec !=. Il existe aussi deux opérateurs & et | de même sens que and et or mais de priorité différente par rapport au test d’égalité.

Pour tous ces opérateurs (sauf ceux d’égalité ou d’inégalité), les nombres non nuls sont associés à True et zéro est assimilé à False.

Documentation Python sur les opérations booléennes
Exercice
  1. Comparer les instructions False == False or True et False == False | True.
  2. Comparer not True and False et not True & False.
  3. Ordonner par priorité croissante les opérateurs ainsi définis.
Pour ces opérateurs, les booléens sont assimilés aux entiers 0 et 1 pour False et True respectivement. Le test d’égalité peut être satisfait entre des nombres de types différents (entier, flottant ou complexe).

Exercice
  1. Comparer les réponses aux commandes 1<2>1, (1<2)>1 et 1<(2>1).

Variables

Lorsqu'une variable sert à affecter une autre variable, les deux variables pointent sur la même valeur. Si on réaffecte l'une des deux, l'autre ne change pas.

originale = 7
copie = originale
originale, copie
(7, 7)
originale = 8
originale, copie
(8, 7)

On peut affecter simultanément deux variables, ce qui permet d'intervertir leurs valeurs en une seule instruction.

a, b = 2, 3
a, b = b, a
a, b
(3, 2)

Types de nombres

En Python 3, les nombres peuvent être de type :

Les calculs avec le type entier sont exacts. Mais la plupart des fonctions du module math renvoient un résultat de type float même s’il est mathématiquement entier. Or le type float est codé en binaire avec une précision de 53 bits. Un nombre aussi simple que 1,1, par exemple, a un développement binaire infini, d’où des approximations plus ou moins surprenantes. Le module decimal permet d’encoder rigoureusement les décimaux pour obtenir un comportement plus satisfaisant dans les calculs. Le module fractions fournit des outils de calcul exacts sur les rationnels. Le module cmath étend certaines des fonctions du module math aux nombres complexes et y ajoute entre autres le calcul de l’argument avec phase.

3*1.1
3.3000000000000003
from decimal import Decimal
3*Decimal('1.1')
Decimal('3.3')
from fractions import Fraction
Fraction('1.1')
Fraction(11, 10)
1j.conjugate()    # conjugaison complexe
-1j
import cmath
cmath.phase(-1)
3.141592653589793

La conjugaison d’un nombre complexe est ici un premier exemple de méthode. On aurait pu imaginer une fonction conjugate qui s’appliquerait à un nombre complexe z en écrivant conjugate(z) mais le choix a été fait d’attacher cette opération au type d’objet utilisé pour modéliser les nombres complexes.

Exercice
  1. Quel est la dixième décimale de la racine carrée de 2 ? Et la centième ?
  2. Quelle est la valeur du nombre complexe ii ?

Les nombres sont des objets Python non mutables, c’est-à-dire que toute opération qui est appliquée à une variable numérique produit une nouvelle variable sans changer l’ancienne.

a = 1+2j
a.conjugate()
1-2j
a
1+2j
Documentation Python sur les types numériques

Le PGCD est accessible dans le module fractions mais le PPCM ou le test de primalité, les algorithmes de factorisation et autres fonctions arithmétiques n’ont pas d’implantation dans la bibliothèque standard.

Générateurs de nombres pseudo-aléatoires

Les générateurs de nombres pseudo-aléatoires s’obtiennent avec le module random.

from random import *
random()    # réel aléatoire entre 0 et 1
0.24107835496252195
[randint(1,6) for i in range(20)]
[4, 6, 5, 1, 1, 4, 5, 5, 3, 3, 5, 4, 6, 3, 6, 4, 3, 1, 4, 1]
l = list(range(10))
shuffle(l)  # mélange de la liste
l
[8, 1, 0, 2, 5, 9, 3, 7, 6, 4]
Exercice
  1. Simuler la somme des valeurs affichées pour le lancer de deux dés équilibrés à 6 faces numérotées de 1 à 6.
  2. Simuler la longueur d’une corde aléatoire sur un cercle de rayon 1.
  3. Simuler les coordonnées d’un point aléatoire de loi de probabilité uniforme sur le disque unité.
  4. Calculer la moyenne et l’écart type d’une série de 100 nombres aléatoires indépendants de loi uniforme sur [0 ; 1].
  5. Évaluer l’espérance de la distance entre deux points aléatoires indépendants suivant une loi uniforme sur un carré de côté 1.
  6. Vérifier le paradoxe des anniversaires sur une classe de 34 élèves.

Fonctions

Il existe plusieurs manières de définir des fonctions. En interface en ligne de commande, il est pratique d’utiliser la définition avec l’opérateur lambda, en particulier avec la fonction reduce du module functools qui permet d’appliquer une fonction de deux variables de gauche à droite dans une liste.

increment = lambda x: x+1
increment(3)
4
from functools import reduce
produit = lambda liste: reduce(lambda x, y : x*y, liste) # produit des termes
produit([2, 3, 5, 2])
60
nb_positifs = lambda liste: reduce(lambda x, y: x+1 if y >= 0 else x, liste, 0)
nb_positifs([-11, -1, 3, 0, -2])
2

La fonction nb_positifs ci-dessus utilise une expression conditionnelle qui n’est valable qu’à partir de la version 3. En outre, le résultat est initialisé non pas par la première valeur de la liste, mais par la valeur 0 précisée en troisième argument.

Documentation Python sur les fonctions
Exercice
  1. Proposer une définition de la fonction factorielle.
  2. Construire la fonction de récurrence de la suite de Syracuse.
  3. Construire une fonction qui supprime les diacritiques d’un mot en français.
  4. Construire une fonction admettant pour arguments un mot en alphabet latin et un nombre entier n et qui décale les lettres de ce mot de n lettres dans l’alphabet.
  5. Construire une fonction qui associe à chaque entier strictement positif la liste de ses diviseurs.

Pour des fonctions utilisant un algorithme interne plus sophistiqué, on emploie en général l’opérateur def, notamment dans la programmation de scripts.

Représentation graphique

L'outil standard de représentation graphique est fourni par le module matplotlib.pyplot. Pour simplifier la saisie, on lui donne un alias.

import matplotlib.pyplot as mp  # on notera mp à la place du nom de module
abscisses = [-1 + k/10 for k in range(31)]  # liste d'abscisses entre -1 et 2
ordonnees = [x**2 for x in abscisses]
mp.plot(abscisses, ordonnees)  # construction du graphique
mp.show()       # affichage

La fenêtre graphique permet de sauvegarder directement le résultat dans un format image (notamment PNG, SVG ou PDF).

Par défaut, on peut encore interagir avec la fenêtre graphique pour rajouter une légende globale ou des étiquettes sur les axes, modifier le cadre d'affichage, changer les couleurs… Mais il vaut mieux préciser toutes les options avant l'affichage, car certains bugs peuvent se produire. Dans ce cas, il suffit de fermer la fenêtre graphique et relancer au besoin la console. L'historique de Spyder permet de récupérer rapidement ce qui a été fait.

c1 = mp.plot(x, y1, "r", marker="o", linestyle=":")  # ronds rouges et pointillés
c2 = mp.plot(x, y2, "g", marker="x", linestyle="--")  # croix vertes et tirets
c3 = mp.plot(x, y3, "y", linewidth=2)  # ligne épaisse jaune
mp.legend((c1, c2, c3), ("courbe de f", "courbe de f'", "courbe de g"))
mp.titre("Un titre explicite et si possible sans accents")

Les indicatifs de couleur sont essentiellement les initiales de noms en anglais (avec k pour noir). Le symbole peut être n'importe quel caractère de +*,.1234<>DH^_dhopsvx|.

Pour reprendre la main sur la console, il vaut mieux fermer la fenêtre graphique.

On pourra consulter la page Tracer les courbes sur math.mad.free.fr

Résolution numérique des équations différentielles

Il ne s'agit pas ici de résoudre formellement des équations différentielles mais d'appliquer des schémas numériques pour obtenir des approximations des solutions.

La subidivision en temps est fournie par le module numpy. Les outils de calcul numérique sont fournis par le module scipy.

import numpy                        # pour subdivision
from scipy.integrate import odeint  # pour résolution
import matplotlib.pylab as mp       # pour graphique
f = lambda y, t: -y  # expression de la dérivée pour y' = -y
y0 = 3               # valeur initiale
temps = numpy.linspace(0, 5, 101)   # [0, 5] subdivisé en 100 intervalles
valeurs = odeint(f, y0, temps)
mp.plot(temps, valeurs)

Pour résoudre une équation du second degré, on transforme l'équation en une équation différentielle vectorielle du premier degré.

F = lambda Y, t: [Y[1], -Y[0]/2]  # expression de la dérivée pour y'' = -y/2
Y0 = [5, 0]                       # y(0) = 5, y'(0) = 0
temps = numpy.linspace(0, 5, 101)
valeurs = odeint(F, Y0, temps)
ordonnees = [terme[0] for terme in valeurs]
mp.plot(temps, ordonnees)

Matrices

On peut définir des matrices comme des listes de listes, mais le module numpy permet un certain nombre de fonctions adaptées au calcul matriciel.

Voir la page Vecteurs, matrices et tableaux sur math.mad.free.fr.