Systèmes informatiques
Fermer ×

Le langage Python

Historique et Présentation

Le langage Python est, à la base, un langage de script interprété, qui a été créé par Guido van Rossum dans les années 1980.

La commande python3 (pour les versions 3) peut être utilisée seule pour une exécution interactive en mode terminal, suivie le nom du fichier python (.py) pour fonctionner en interpréteur, ou encore avec le module py_compile pour compiler le code python. Dans ce dernier cas, le fichier exécutable possède l'extension .pyc et se trouve dans le répertoire __pycache__.

Ce qui suit est inspiré de ce site sur la programmation en python et de la documentation plus complète du site python.

Avertissement : tous les exemples de programmes python ont été testés sous linux.

Il peut être utilisé comme un langage de script shell linux. Exemple avec le programme hello.py


#!/usr/bin/python3

print("bonjour le monde")
				

L'exécution de ce programme se fait avec la commande

pyhton3 hello.py
dans le répertoire du fichier, sinon il faut ajouter le chemin d'accès.

Sous linux, si le fichier est exécutable et si la première ligne contient la commande spécifique d'accès à l'interpréteur, il peut être utilisé directement comme une commande linux.

Il peut être structuré sous forme procédurale comme le langage C


def main(args):
	print("bonjour le monde")	
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
				

import sys importe le module sys qui contient les fonctions d'accès au système d'exploitation. sys.exit(code) termine le programme avec le code qui correspond au code de retour de la fonction main. La variable __name__ contient __main__, cela correspond au module directement exécuté. si ce module est exécuté à partir d'un autre module, cette variable contient le nom du module.

Exemple :

Fichier module1.py


from module2 import main

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
				

La première ligne indique que l'on importe la fonction main de module2.

fichier module2.py


def main(args):
	print(__name__)
	print("bonjour le monde")	
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
				

L'exécution de module1.py affiche

module2
bonjour le monde
				

L'exécution de module2.py affiche

__main__
bonjour le monde
				

En python, il n'y a pas de caractère de fin d'instruction, ni de caractères de début et de fin de bloc. On a une ligne par instruction et une indentation (tabulation) par niveau d'imbrication de bloc.

Enfin, le langage Python peut être également structuré en langage objet comme le langage C++

fichier Affichage.py qui contient la classe Message


class Message:
	def __init__(self,typemessage):
		self.entete = typemessage
		
	def afficher(self,message):
		print(self.entete + " " + message)
				

La fonction __init__ correspond au constructeur. Le paramètre self, n'est pas transmis au constructeur ni aux méthodes. Il représente l'objet courant.

Utilisation de la classe Message


from Affichage import Message

def main(args):
	affichage = Message("info : ")
	affichage.afficher("bonjour le monde")	
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
				

Syntaxe et structure du langage

Les types de données

En python, les types des données peuvent être :

typedésignationfonction
intentier non limitéint()
floatréel double précision IEEE 754float()
complexcomplexe avec j pour la représentation de l'imaginairecomplex()
strChaîne de caractèresstr()
boolbooléen : True ou False, où False correspond à une valeur numérique nulle ou encore à une chaîne videbool()
NoneTypesans type de valeur None

Les valeurs entières sont écrites en base décimale (base 10) par défaut, mais elle peuvent être écrites en hexadécimal en utilisant le préfixe 0x ou encore en octal (base 8) en utilisant le préfixe 0.

Les fonctions permettent de forcer le type ou bien d'effectuer un transtypage.

Les variables

Les variables ne sont pas déclarées, sauf s'il est nécessaire de les initialiser. Le type de la variable est défini automatiquement lors de l'affectation d'une valeur constante ou bien du résultat de l'expression de calcul.

La fonction type(nomvariable) permet de connaître le type de la variable.

Les variables de type chaînes de caractères

Les délimiteurs des chaînes de caractères sont les guillemets.

Le langage python fournit un ensemble de fonctions de chaînes de caractères. Pour les utiliser, il faut faire suivre le nom de la chaîne par le nom de la fonction séparée par un point. Parmi toutes ces fonctions, on peut citer :

Toutes les fonctions créent une nouvelle chaine, la chaine d'origine (variablechaine) n'est pas modifiée.

L'affectation

Le symbole d'affectation est le signe =. L'expression située à droite du symbole = est évaluée, le résultat est affecté à la variable située à gauche du symbole =. Le type de cette variable est défini en fonction du type du résultat.

La conversion entre types

Elle peut être effectué en utilisant les fonctions associées aux types, comme par exemple prendre la partie entière d'un réel.


reel = 8.62
print(reel)
entier = int(reel*100)
print(entier)
				

L'affichage est

8.62
861
				

On peut observer qu'il y a une erreur de calcul, car 8.62 × 100=862. 8.62 × 100 donne une valeur approchée 861.9999, ce qui fait que la valeur de la partie entière est 861. Cette erreur a déjà été constatée avec octave et scilab et avec le langage C. Cela est du au mode d'enregistrement et de calcul de la machine.

Les opérateurs

Opérateurs arithmétiques

OpérateurOpérationOpérandes
+additionentiers, réels, complexes, chaînes (concaténation), joindre certains type de listes (list, tuple)
-soustractionentiers, réels, complexes
*multiplicationentiers, réels, complexes
/division réelleentiers, réels, complexes
//division entièreentiers, réels
%moduloentiers
**puissanceentiers, réels, complexes pour les 2 opérandes

Opérateurs de comparaisons

Le résultat d'une comparaison est de type booléen.

OpérateurComparaisonOpérandes
==égalitéentiers, chaînes
!=différent deentiers, chaînes
<inférieur àentiers, réels, chaînes
>supérieur à entiers, réels, chaînes
<=inférieur ou égal àentiers, réels, chaînes
>=supérieur ou égal àentiers, réels, chaînes

Pour les chaînes de caractères la comparaison est lexicographique.

Opérateurs logiques

Il fonctionnent avec des booléens.

OpérateurOpérationOpérandes
orVrai si au moins une opérande est vraiebooléen
andFaux si au moins une opérande est faussebooléen
notInverse la valeur booléenne de l'opérandebooléen

Opérateurs bits à bits

Ils effectuent des opérations logiques sur chaque bit des opérandes au sens de la représentation binaire des entiers.

OpérateurOpérationOpérandes
&ETentiers, ensembles (set)
|OUentiers, ensembles (set)
^OU exclusifentiers
~inversion bit par bitentiers
<<décalage à gauche de n bits (2ème opérande)entiers
>>décalage à droite de n bits (2ème opérande)entiers

Affectation et opérateurs combinés

L'opérande de gauche est calculée avec l'expression de droite, le résultat est affecté à l'opérande de gauche

OpérateurOpérationOpérandes
+=additionentiers, réels, complexes, chaînes (concaténation)
-=soustractionentiers, réels, complexes
*multiplicationentiers, réels, complexes
/=division réelleentiers, réels, complexes
//=division entièreentiers, réels
%=moduloentiers
**=puissanceentiers, réels, complexes pour les 2 opérandes
&=ETentiers
|=OUentiers
^=OU exclusifentiers
<<=décalage à gauche de n bits (2ème opérande)entiers
>>=décalage à droite de n bits (2ème opérande)entiers

L'entrée et la sortie standard

Affichage sur la sortie standard

Cela se fait avec la fonction print(variable) qui permet d'afficher la valeur d'une variable sur la sortie standard suivi d'un retour à la ligne suivante.

Pour afficher des valeurs de variables combinées avec du texte, il faut soit convertir les autres types en chaîne de caractères (str) et concaténer l'ensemble, soit utiliser une chaîne de formatage de la forme :

f"texte {variable} ...."

où chaque variable est entre accolade et peut être suivie de caractères de formatage, comme par exemple :

Le détail des formats est disponible sur la partie python du site w3schools

Il est également possible de formater l'affichage des variables avec la fonction format(liste variables) où le format d'affichage est précisé entre accolades sans la variable et la variable transmise à la fonction format sous la forme chaineformat.format(liste des variables).

Saisie sur l'entrée standard

Elle utilise la fonction input(texte), où texte est le texte à afficher avant d'attendre la saisie. la fonction retourne la saisie sous la forme d'une chaîne de caractères. Dans le cas de saisie de nombres, il faudra effectuer la conversion de type adaptée avant de faire les calculs.

Les structures de contrôle

L'alternative

Elle permet d'effectuer un traitement en fonction d'un résultat booléen

if (expression booleenne):
	traitement si expression booleenne vraie
elif (expression booleene 2):
	traitement si expression booleenne 2 varie
else:
	traitement dans les autres cas

Les traitements sont décalés (indentés) d'une tabulation par rapport au niveau d'indentation de if. Les blocs elif et else ne sont pas obligatoires.

Exemple de résolution d'équation de degré 2 dans ℂ

Voir le code de résolution d'une équation de second degré

Fichier equation_degre2.py


from math import *

def main(args):
	ch_a=input("a? ")
	ch_b=input("b? ")
	ch_c=input("c? ")
	a=float(ch_a)
	b=float(ch_b)
	c=float(ch_c)
	delta=b**2-4*a*c
	print(f"delta={delta}")
	if (delta > 0):
		x1 = (-b-sqrt(delta))/(2*a)
		x2 = (-b+sqrt(delta))/(2*a)
		print(f"x1={x1} , x2={x2}")
	elif (delta == 0):
		x = (-b)/(2*a)
		print(f"x={x}")
	else:
		x1 = (-b-sqrt(-delta)*1j)/(2*a)
		x2 = (-b+sqrt(-delta)*1j)/(2*a)
		print(f"x1={x1} , x2={x2}")
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
					

On remarque les différentes tabulations qui permettent de définir les imbrications des blocs de l'alternative.

Le calcul de la racine carrée fait appel à la fonction sqrt du module math.

La saisie des coefficients donne des chaînes de caractères identifiées ch_a,ch_b st ch_c qui sont ensuite converties en réels, respectivement a,b,c. Ensuite on calcule Δ et l'affiche sur la sortie standard.

En fonction du signe de Δ on effectue le traitement approprié et affiche le ou les résultats. Dans le cas ou Δ est négatif, on calcule la racine carrée de -Δ et on la multiplie par 1j pour obtenir une valeur imaginaire.

Les répétitions

for variable in liste:
	traitement
				
  • Le bloc traitement est effectué pour chaque élément de la liste affecté à variable. Le nombre de répétitions de traitement est égal au nombre d'éléments de la liste.

La liste peut être crée avec la fonction range(val1,val2)val1 est la première valeur, et val2 la dernière valeur +1 . Ce qui fait que variable varie de val1 à val2-1, si val1 n'est pas précisée, elle vaut implicitement 0

while (expression booleenne):
	traitement
				
  • Le bloc traitement est exécuté tant que l’expression booléenne est vraie.
  • L’expression booléenne est vérifiée avant d’exécuter le bloc traitement, ce qui impose que la valeur de cette expression booléenne doit être initialisée avant d’exécuter cette boucle.
  • Le bloc traitement peut ne pas être exécuté
Voir le code d'affichage d'une table de multiplication

Fichier table_multiplication.py


def main(args):
	ch_m=input("table des ")
	m=int(ch_m)
	for i in range(1,11):
		p=m*i
		print(f"{m:2d} X {i:2d} = {p:2d}")
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
					

La valeur du multiplicateur de la table est saisie sur l'entrée standard, puis convertie en entier. Les valeurs sont alignées à droite sur 2 colonnes.

Affichage des résultats pour m=3

table des 3
 3 X  1 =  3
 3 X  2 =  6
 3 X  3 =  9
 3 X  4 = 12
 3 X  5 = 15
 3 X  6 = 18
 3 X  7 = 21
 3 X  8 = 24
 3 X  9 = 27
 3 X 10 = 30
					
Voir le code de calcul d'une suite

Fichier suite.py


def main(args):
	un=0.7
	for i in range(1,31) :
		un = 10*un-6.3
		print(f"{i} : {un}")
	return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))
					

On reprend le calcul de la suite présentée dans le chapitre sur les suites et séries

On remarque que l'on trouve toujours la même divergence alors que cette suite est mathématiquement constante et vaut toujours 0.7. On retrouve donc le problème d'arrondi dans les calculs des réels, qui cette fois, se cumulent.

Affichage des résultats

1 : 0.7000000000000002
2 : 0.700000000000002
3 : 0.7000000000000197
4 : 0.7000000000001974
5 : 0.7000000000019737
6 : 0.7000000000197373
7 : 0.700000000197373
8 : 0.7000000019737298
9 : 0.7000000197372982
10 : 0.7000001973729821
11 : 0.7000019737298215
12 : 0.7000197372982155
13 : 0.7001973729821556
14 : 0.7019737298215558
15 : 0.7197372982155583
16 : 0.8973729821555834
17 : 2.673729821555834
18 : 20.43729821555834
19 : 198.0729821555834
20 : 1974.429821555834
21 : 19737.998215558342
22 : 197373.68215558343
23 : 1973730.5215558342
24 : 19737298.915558342
25 : 197372982.8555834
26 : 1973729822.255834
27 : 19737298216.258343
28 : 197372982156.28345
29 : 1973729821556.5344
30 : 19737298215559.043
					

Les structures de données

Les listes (list)

Les listes sont des suites de variables ordonnées. Elles peuvent être utilisées pour implémenter des tableaux.

L'initialisation se fait avec une liste de données entre crochets et séparés par une virgule, comme par exemple :
listeentiers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
pour un tableau des entiers de 1 à 10.
Il est possible de définir la liste précédente à l'aide d'une répétition :
listeentiers = [ i for i in range(1,11) ]
L'accès à un élément se fait avec le nom de la liste suivi de l'indice entre crochets, comme par exemple :
listeentiers[3]
qui vaut 4, car le premier indice est 0.

Les principales fonctions de traitement des listes sont :

Il est possible de joindre deux listes avec l'opérateur +

Voir le code d'affichage d'une table de multiplication utilisant une liste

Fichier table_multiplication.py


listn = [ i for i in range(1,11) ]

def main(args):
	ch_m=input("m ? ")
	m=int(ch_m)
	for i in listn:
		p=m*i
		print(f"{m:2d} X {i:2d} = {p:2d}")
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
					

Affichage des résultats pour m=3

table des 3
 3 X  1 =  3
 3 X  2 =  6
 3 X  3 =  9
 3 X  4 = 12
 3 X  5 = 15
 3 X  6 = 18
 3 X  7 = 21
 3 X  8 = 24
 3 X  9 = 27
 3 X 10 = 30
					

Les listes non modifiables (tuple)

Les listes non modifiables (tuple) sont des suites de variables ordonnées. On ne peut pas ajouter de valeur ni les modifier.

L'initialisation se fait avec une liste de données entre parenthèses et séparés par une virgule, comme par exemple :
listeentiers = ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 )
pour un tableau des entiers de 1 à 10.
Il est possible de définir la liste précédente à l'aide d'une répétition :
listeentiers = ( i for i in range(1,11) )
L'accès à un élément se fait avec le nom de la liste suivi de l'indice entre crochets, comme par exemple :
listeentiers[3]
qui vaut 4, car le premier indice est 0.

Les principales fonctions de traitement des listes sont :

Il est possible de joindre deux listes avec l'opérateur +

Voir le code d'affichage d'une table de multiplication utilisant une liste non modifiable

Fichier table_multiplication.py


listn = ( i for i in range(1,11) )

def main(args):
	ch_m=input("m ? ")
	m=int(ch_m)
	for i in listn:
		p=m*i
		print(f"{m:2d} X {i:2d} = {p:2d}")
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
					

Affichage des résultats pour m=3

table des 3
 3 X  1 =  3
 3 X  2 =  6
 3 X  3 =  9
 3 X  4 = 12
 3 X  5 = 15
 3 X  6 = 18
 3 X  7 = 21
 3 X  8 = 24
 3 X  9 = 27
 3 X 10 = 30
					

Les dictionnaires (dictionary)

Un dictionnaire est une suite de paires <clé,valeur>. On accède à la valeur par l'intermédiaire de la clé.

L'initialisation se fait avec une liste de cle:valeur entre accolades séparées par des virgules, comme par exemple :
dict={ "x" : "y" , "a" : "b"}
L'accès à un élément se fait avec le nom du dictionnaire suivi de la clé entre crochets, comme par exemple :
dict["x"]
qui vaut "y".

Les principales fonctions de traitement des dictionnaires sont :

Les ensembles (set)

Les ensembles sont des suites de variables non ordonnées. Les valeurs ne peuvent être dupliquées. C'est un ensemble au sens mathématique du terme.

L'initialisation se fait avec une liste de données entre accolades et séparés par une virgule, comme par exemple :
A = { 1, 2, 3, 4, 5 }
pour l'ensemble des entiers compris entre 1 et 5
Il est possible de définir la liste précédente à l'aide d'une répétition :
A={i for i in range(6)}
Il n'y a pas d'accès à un élément particulier avec un indice comme c'est le cas avec les autres structures de données.

Les principales fonctions de traitement des ensembles sont :

Fonction pour ces structures de données

Les fonctions

Les fonctions sans paramètres

Ces fonctions sont utilisées pour l'affichage de message.

Une fonction de déclare avec le mot clé def suivi du nom de la fonction :

def nomfonction():
	traitement
				

Les fonctions avec paramètres

Ce type de fonction utilise les paramètres transmis

def nomfonction(liste parametres):
	traitement
				

Les paramètres par valeur concernent les entiers, réels, complexes, chaînes de caractères. Une modification du contenu par la fonction n'est pas transmise à la fonction qui l'a appelée

Les paramètres par références concernent les liste, dictionnaires et objets. Une modification du contenu par la fonction est transmise à la fonction qui l'a appelée

Les valeurs de retour des fonctions

C'est une fonction avec ou sans paramètres qui renvoie une valeur.

def nomfonction(liste parametres):
	traitement et calcul de la valeur de retour
	return valeurretour
		

Il est possible d'avoir un retour avec une liste de valeurs, ce qui permet de compenser l'absence de paramètres par référence pour les entiers, réels, complexes.

Exemples

Voir le code de la fonction de calcul de la multifactorielle

Fichier multifactorielle.py


def multifactorielle(n,k):
	f=1
	if (n>1):
		f=multifactorielle(n-k,k)*n
	return f

listen = [ i+1 for i in range(10)]

def main(args):
	ch_k=input("k ? ")
	k=int(ch_k)
	for i in listen:
		f=multifactorielle(i,k)
		print(f"{i}!{k}={f}")
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
					

Affichage des résultats

k ? 2
1!2=1
2!2=2
3!2=3
4!2=8
5!2=15
6!2=48
7!2=105
8!2=384
9!2=945
10!2=3840
					

La multifactorielle est présentée dans la chapitre sur les logiciels mathématiques

La fonction utilise la récursivité.

Voir le code de la fonction echange

Fichier echange.py


def echange(x,y):
	tmp=x
	x=y
	y=tmp
	return x,y

def main(args):
	ch_a=input("a ? ")
	ch_b=input("b ? ")
	a=float(a)
	b=float(b)
	print(f"a={a} b={b}")
	a,b=echange(a,b)
	print(f"a={a} b={b}")
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
					

Exemple d'utilisation et affichage des résultats

a ? 1.2
b ? 9.6
a=1.2 b=9.6
a=9.6 b=1.2
					

La portée des variables

Toutes les variables sont locales aux fonctions dans lesquelles elles ont été utilisées.

Une variable déclarée en dehors des fonctions est une variable globale qui est accessible par toutes les fonctions mais non modifiable par ces fonctions.

Si cette variable globale est déclarée avec le mot clé global dans une fonction, alors elle est modifiable par cette fonction.

La gestion des fichiers

Ouverture et fermeture

L'ouverture se fait avec la fonction open qui retourne un objet. L'accès au contenu du fichier se fait avec les méthodes de cette objet.

fd=open(nomfichier,mode)

avec nomfichier qui est le nom du fichier avec son chemin et mode, composé de plusieurs lettres, qui est le mode d'accès au fichier.
La première lettre est soit

Cette première lettre peut être suivie d'un "+" (optionnel) pour passer en mode lecture et mise à jour.

La lettre suivante représente le type de fichier

La fermeture se fait avec la méthode close de l'objet renvoyé par open

fd.close()

Gestion des erreurs

Les fonctions d'accès au fichier nécessitent l'utilisation de la structure try...except

try:
	traitement normal du fichier
except TYPEXCEPTION:
	affichage de message
		
TYPEXCEPTION peut être, par exemple :

Il peut y avoir plusieurs blocs except afin de gérer plusieurs erreurs différentes.

Lecture

Mode texte

La lecture peut se faire sur le fichier entier avec objetfichier.readlines() ou bien ligne par ligne avec objetfichier.readline().

readlines() renvoie un liste de chaînes ou chaque élément correspond à une ligne incluant les caractères de fin de ligne.

readline() renvoie une chaîne de caractères qui contient la ligne en incluant les caractères de fin de ligne

Voir le code pour la lecture d'un fichier texte

Lecture du texte avec readlines


def main(args):
	nomfichier=args[1]
	try:
		fd=open(nomfichier,"r")
		texte = fd.readlines()
		for ligne in texte:
			print(ligne.rstrip("\n"))
		fd.close()
	except FileNotFoundError:
		print("fichier non trouve")
	return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))
					

Lecture ligne par ligne avec readline


def main(args):
	nomfichier=args[1]
	try:
		fd=open(nomfichier,"r")
		ligne = fd.readline()
		while (ligne):
			print(ligne.rstrip("\n"))
			ligne = fd.readline()
		fd.close()
	except FileNotFoundError:
		print("fichier non trouve")
	return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))
					

Le nom du fichier est transmis sur la ligne de commande à la suite du nom du fichier python.

Ici on ne traite que l'erreur de fichier non trouvé, qui affiche le message d'erreur sur la sortie standard.

Mode binaire

La lecture se fait avec la fonction objetfichier.read(taille) avec taille qui représente le nombre d'octets à lire. Cette fonction renvoie une liste d'octets.

Voir le code pour la lecture d'un fichier binaire

def main(args):
	nomfichier=args[1]
	try:
		fd=open(nomfichier,"rb")
		octets = fd.read(1)
		while (len(octets)>0):
			print(octets[0])
			octets=fd.read(1)
		fd.close()
	except FileNotFoundError:
		print("fichier non trouve")
	return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))
					

Le nom du fichier est transmis en ligne de commande

Dans cet exemple, on lit le fichier octet par octet, ce qui n'est pas toujours la meilleur solution. Le nombre d'octets à lire doit être choisi en fonction du type des données enregistrées.

Quelque soit la taille demandée, la fonction renvoie une liste.

Ici on ne traite que l'erreur de fichier non trouvé, qui affiche le message d'erreur sur la sortie standard.

Ecriture

Mode texte

L'écriture se fait avec la fonction objetfichier.write(chaine)chaine est une chaîne de caractères. Les autres types de données doivent être convertis en chaîne de caractères formatée si nécessaire.

Voir le code pour l'écriture d'un fichier texte

def main(args):
	nomfichier=args[1]
	try:
		fd=open(nomfichier,"w")
		ch_a=input("a= ")
		fd.write(ch_a)
		fd.close()
	except IOError:
		print("Erreur")
	return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))
					

L'entier est converti en chaîne de caractères afin de pouvoir être utilisé avec la fonction write.

Ici on traite que l'ensemble des erreurs d'entrées sorties sans plus de précision.

Mode binaire

L'écriture se fait avec la fonction objetfichier.write(octets)octets est un tableau d'octets Les autres types de données doivent être convertis en tableau d'octets si nécessaire.

Dans le cas d'un entier on peut utiliser la conversion vers un tableau d'octet du type entier e.to_bytes(taille,format) avec e qui est l'entier , taille le nombre d'octets et format qui correspond à l'ordre dans lequel sont enregistrés les octets de l'entier big endian ou little endian.

Voir le code pour l'écriture d'un fichier binaire

def main(args):
	nomfichier=args[1]
	try:
		fd=open(nomfichier,"wb")
		ch_a=input("a ? ")
		a=int(ch_a)
		fd.write(a.to_bytes(4,"little"))
		fd.close()
	except IOError:
		print("Erreur")
	return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))
					

L'entier est enregistré sur 4 octets (32 bits) au format little endian

Les mathématiques

Le module math

Ce module contient l'ensemble des fonctions mathématiques standard pour les nombres réels : trigonométrie, exponentielle, logarithme.

Voir le code pour l'utilisation du module math pour le traitement des complexes

module complexes.py


from math import *

def complexe_module(c):
	m=abs(c)
	return m

def complexe_arg(c):
	a=atan2(c.imag,c.real)
	return a

def complexe_conjugue(c):
	cbar=c.conjugate()
	return cbar
					

la fonction atan2(y,x) permet de calculer l'angle sur l'ensemble du cercle trigonométrique.

Le type complexe permet d'extraire la partie réelle, imaginaire et de calculer le conjugué.

test du module complexes.py


from complexes import *

def main(args):
	z=2+3j
	m=complexe_module(z)
	print(f"||{z}|| = {m}")
	a=complexe_arg(z)
	print(f"arg({z}) = {a}")
	zbar=complexe_conjugue(z)
	ligne = "{}/ = {}"
	print(f"/{z} = {zbar}")	
	zp = z * zbar
	m2=m**2
	print(f"||{z}||^2 = {zp.real} = {m2}")	
	return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))
					

Affichage du résultat

||(2+3j)|| = 3.605551275463989
arg((2+3j)) = 0.982793723247329
/(2+3j) = (2-3j)
||(2+3j)||^2 = 13.0 = 12.999999999999998			
					

Les complexes et le module cmath

Le module cmath permet d'utiliser les différentes fonctions mathématiques pour les nombres complexes.

Exemple de fonctions disponibles

Les matrices et le module numpy

Le module numpy permet d'effectuer des calculs matriciels.

Les matrices sont représentées par des tableaux avec le type array de ce module. Ce module permet d'effectuer les opérations sur les matrices comme, par exemple, l'addition avec l'opérateur +, la transposition, le produit (dot).

Voir un exemple d'utilisation des fonctions de calcul matriciel

import numpy as np

def main(args):
	A=np.array([[1,2],[3,4]])
	B=np.array([[4,6],[1,5]])
	S=A+B
	P=np.dot(A,B)
	Bt=B.T
	print(A)
	print(B)
	print(S)
	print(P)
	print(Bt)
	return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))
					

Affichage du résultat

[[1 2]
 [3 4]]
[[4 6]
 [1 5]]
[[5 8]
 [4 9]]
[[ 6 16]
 [16 38]]
[[4 1]
 [6 5]]
					

Représentation graphique

Le module matplotlib permet de tracer des graphiques avec une syntaxe proche du logiciel octave

Tracé d'une courbe

L'essentiel des fonctions pour tracer une courbe sont
Voir un exemple de tracé d'une fonction polynomiale

import matplotlib.pyplot as plt
import numpy as np

def Horner(coeffs,x):
	nb=len(coeffs)
	y=coeffs[nb-1]
	for i in range(nb-1):
		y=coeffs[nb-i-2]+x*y
	return y

def main(args):
	coeffs=[15, 16, 6 , 1]
	lx = np.linspace(-7, 3, 100)
	ly= []
	for x in lx:
		y=Horner(coeffs,x)
		ly.append(y)
	plt.plot(lx,ly)
	plt.xlabel('x')
	plt.ylabel('y')
	plt.axis([-7,3,-150,150])
	plt.title("Fonction polynomiale")
	plt.grid()
	plt.show()
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
					

Affichage du résultat

L'évaluation de la fonction polynomiale utilise la méthode de Horner

Tracé d'un camembert

Ce tracé utilise la fonction
Voir un exemple de tracé du camembert de la facture d'électricité

import matplotlib.pyplot as plt
import numpy as np

def main(args):
	abonnement=34.01
	consommation=46.62
	taxes=12.71
	contribution=6.65
	etiquettes = ["abonnement", "consommation", "taxes et contributions", "contributions"]
	extraire = [0, 0.3, 0, 0]
	couleurs = ["yellow", "green", "orange", "red"]
	donnees = np.array([abonnement, consommation, taxes, contribution])
	plt.pie(donnees,labels=etiquettes,explode=extraire,colors=couleurs,shadow = False)
	plt.show()
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
					

Affichage du résultat

Tracé du diagramme de Venn

Ce tracé se fait en utilisant le module matplotlib_venn

L'essentiel des fonctions pour tracer une courbe sont
Voir un exemple de tracé du diagramme de Venn du deuxième ensemble du thème math

import matplotlib.pyplot as plt
from matplotlib_venn import venn2

def main(args):
	A={0,1,2,3,4,5}
	B={4,5,6,7,8,9}
	C=set(map(str,A-B))
	D=set(map(str,B-A))
	E=set(map(str,A & B))
	venn=venn2((A,B),('A','B'))
	venn.get_label_by_id('10').set_text(';'.join(C))
	venn.get_label_by_id('01').set_text(';'.join(D))
	venn.get_label_by_id('11').set_text(';'.join(E))
	plt.show()
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
					

Affichage du résultat

Programmation objet

Définitions

Le concept objet a été présenté avec le langage C++. On présente donc la syntaxe objet en python

class nom_classe:

	def __init__(self,parametres):
		# initialisation des attributs
		self.attribut = 
		seld.__attribut = 

	def methode(self,parametres):
		# traitement
		# eventuellement valeur de retour
		return valeurretour
		
	def __add__(self,parametres):
		# traitement
		return objet
				

__init__ est le constructeur.

le mot clé self correspond à l'objet courant, il n'apparaît plus lors de l'utilisation des méthodes.

Un attribut précédé des deux caractères "_" est un attribut privé.

La méthode __add__ correspond à la surcharge de l'opérateur +, cette surcharge s'applique à d'autres opérateurs comme :

  • __sub__ pour la soustraction
  • __mul__ pour la multiplication
  • __truediv__ pour la division réelle
  • __pow__ pour la puissance

Une méthode de surcharge retourne un objet correspondant au type de la classe.

Voir un exemple avec la classe complexe

fichier complexes.py


from math import *

class Complexe():
	def __init__(self,c):
		self.__z = c
		
	def get(self):
		return self.__z

	def module(self):
		m=abs(self.__z)
		return m
		
	def argument(self):
		a=atan2(self.__z.imag,self.__z.real)
		return a
	
	def conjugue(self):
		zbar=self.__z.conjugate()
		return Complexe(zbar)

	def __add__(self,z2):
		s = self.__z + z2.get()
		return Complexe(s)
		
	def __sub__(self,z2):
		d = self.__z + z2.get()
		return Complexe(d)
	
	def __mul__(self,z2):
		p = self.__z * z2.get()
		return Complexe(p)
		
	def __truediv__(self,z2):
		q = self.__z / z2.get()
		return Complexe(q)
					

Fichier de text de la classe complexe


from complexes import Complexe

def main(args):
	z1=Complexe(1+3j)
	z2=Complexe(1+1j)
	m1=z1.module()
	print(f"||{z1.get()}|| = {m1}")
	a1=z1.argument()
	print(f"arg({z1.get()}) = {a1}")
	z1bar=z1.conjugue()
	print(f"/{z1.get()} = {z1bar.get()}")	
	zs = z1 + z2
	print(f"{z1.get()} + {z2.get()} = {zs.get()}")	
	zp = z1 * z2
	print(f"{z1.get()} X {z2.get()} = {zp.get()}")	
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))
					

Cette classe permet de présenter la structure d'une classe, mais n'est pas forcément utile car python permet de traiter les nombres complexes avec le module cmath présenté auparavant.

Le constructeur utilise un type complex déjà défini en python. La classe Complexe contient un attribut privé __z de type complex

La méthode get renvoie la valeur de l'attribut privé __z de type complex.

Les méthodes effectuent les calculs sur des types complex. Les méthodes de surcharge retourne un objet de la classe Complexe.

Héritage

from module import classe_parent
					
class nom_classe(classe_parent):

	def __init__(self,parametres):
		classe_parent.__init__(parametres parents)
		# initialisation des attributs
		self.attribut = 
		seld.__attribut = 
		
	def methode(self,parametres):
		pass

	def methode(self,parametres):
		# traitement
		# eventuellement valeur de retour
		return valeurretour
				

Il faut importer le module qui contient la classe parent.

La classe parent est précisée entre parenthèses.

L'appel du constructeur de la classe parent se fait avec la syntaxe classe_parent.__init__(parametres) où les paramètres sont ceux du constructeur de la classe parent.

Une méthode dont le seul contenu est le mot clé pass est une méthode abstraite qui devra être redéfinie dans la classe fille.

Héritage multiple

from module import classe1
from module2 import classe2
					
class nom_classe(classe1,classe2):

	def __init__(self,parametres):
		classe1.__init__(parametres parents1)
		classe2.__init__(parametres parents2)
		# initialisation des attributs
		self.attribut = 
		seld.__attribut = 

	def methode(self,parametres):
		# traitement
		# eventuellement valeur de retour
		return valeurretour
				

Il faut également importer tous les modules qui définissent les classes parent

La liste des classes parents est définie entre parenthèses.

Dans le constructeur, on peut appeler le constructeur de chaque classe parent avec les paramètres correspondants aux paramètres des constructeurs des classes parents.

Exemple de calcul de l'intégrale d'une fonction polynomiale déjà vue en C++

Voir le code des classes Polynome et Integrale

fichier Polynome.py


class Polynome():
	
	def __init__(self,p):
		self.coeffs = p
		self.taille = len(p)
	
	def Horner(self,x):
		y = self.coeffs[self.taille-1]
		for i in range(self.taille-1):
			y = self.coeffs[self.taille-i-2]+x*y
		return y
					

Comme pour le tracé de courbe avec matplotlib, l'évaluation du polynôme se fait avec la méthode de Horner.

Comme pour la version C++, le calcul de l'intégrale utilise la méthode des trapèzes.

fonction est la méthode abstraite qui devra être redéfinie dans la classe fille.

fichier Integrale.py


class Integrale():
	
	def __init__(self,a,b):
		self.a = a
		self.b = b
		self.dx = 0.01
		
	def fonction(self,x):
		pass
		
	def calculer(self):
		total = 0
		n = (self.b-self.a)/self.dx
		x0=self.a
		while x0 < self.b:
			total += (self.fonction(x0)+self.fonction(x0+self.dx))*self.dx/2
			x0 += self.dx
		return total;
					
Voir le code de la classe fille et du programme de test

fichier IntegralePolynome


from Integrale import Integrale
from Polynome import Polynome

class IntegralePolynome(Integrale,Polynome):
	
	def __init__(self,p,a,b):
		Integrale.__init__(self,a,b)
		Polynome.__init__(self,p)
	
	def fonction(self,x):
		return self.Horner(x)
					

La méthode fonction appelle la méthode Horner de la classe parent Polynome

fichier de test


from IntegralePolynome import IntegralePolynome

def main(args):
	polynome = [ -1 , 0.5 ]
	integralepoly=IntegralePolynome(polynome,2,6)
	aire = integralepoly.calculer()
	print(f"aire = {aire}")
	return 0

if __name__ == '__main__':
	import sys
	sys.exit(main(sys.argv))