Mémo Python
Michel Llibre - Juin 2025
ATTENTION : Lire le chapitre Préliminaires à propos des différents interpréteurs accessibles sous windows.
Documentation générale :
•https://python.sdv.univ-paris-diderot.fr/ : Un véritable cours très complet et bien structuré que l'on peut télécharger en pdf (https://python.sdv.univ-paris-diderot.fr/cours-python.pdf) et qui existe également en livre chez Dunod.
•https://docs.python.org/fr/3/tutorial/ : Un monument d'apprentissage en français, à suivre pas à pas, mais qui ne permet pas d'accéder facilement à la réponse à une question qu'on se pose.
•https://docs.python.org/fr/3/reference/ : La référence du langage en français. Un pavé. Quand on se pose une question sur un mot clé du langage de base (if, for, return...).
•https://docs.python.org/fr/3/library/ : Idem quand on se pose une question sur un objet du langage ou une fonction de base (float, string, print...).
•http://pascal.ortiz.free.fr/ : Un site d'apprentissage en français avec beaucoup de vidéos thématiques sur les différents concepts du langage de programmation Python. La documentation sur tkinter est intéressante.
Documentation sur tkinter, la librairie pour interface utilisateur graphique (GUI) la plus utilisée avec Python :
•http://pascal.ortiz.free.fr/contents/tkinter/tkinter/index.html : La documention en français de Pascal Ortiz, déjà mentionnée.
•tkinter.fdex.eu/doc/ : Une documentation en français très bien structurée et bien documentée.
•http://effbot.org/tkinterbook/ : Une documentation en anglais avec un accès alphabétique.
•http://www.scoberlin.de/content/media/http/informatik/tkinter/index.htm : La référence de tkinter en anglais, un peu austère, ancienne, mais très complète.
Un livre (pdf) d'apprentissage de Python pour les enfants - version française):
https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/swfk-fr/swfk-fr_0.0.9.pdf
Télécharger et installer Python (>= 3.6) : https://www.python.org/
Après cette installation on dispose d'un IDE (pythonw.exe) accessible dans le menu des applis windows : Python IDLE . Cet IDE est constitué d'une console d'exécution des programmes Python et d'un éditeur de code source.
Dans la fenêtre console on exécute les instructions python comme si on avait appelé python en ligne commande.
Dans la fenêtre d'édition, on peut faire exécuter le code qui s'y trouve dans la console en appuyant sur la touche F5 (menu Run > Run Module de le fenêtre d'édition).
L'interpréteur python est activé par une des 3 commandes suivantes : py, python, python3.., et éventuellement par les 3. Si on tape une de ces commandes on ouvre le premier interpréteur accessible dans le path système, qui peut ne pas être celui que l'on veut exécuter (pas à jour ou n'ayant pas les librairies nécessaires...), car il y a parfois sous windows un interpréteurs python ancien déjà installé. De plus on peut être emmené vers le "Windows Store" si on tape une commande qui ne correspond à rien d'installé (python3 par exemple, même si on l'a installé depuis https://www.python.org/ car il apparait sous le nom python et non pas python3).
Au début, il faut donc lever ces ambiguités : Les commandes dos where py et where python vont donner less chemins (path système) de ces commandes. Il faut s'assurer que le premier de la liste est celui que l'on veut exécuter. Si ce n'est pas le cas on a intérêt à modifier path système :
Pour celà il faut aller dans la fenêtre des "Propriétés système" de Windows en suivant par exemple, la procédure suivante :
•taper path dans la ligne de recherche des paramètres Windows
•choisir "Modifier les variables d'environnement système")
•Dans l'onglet "Paramètres système avancés" cliquer sur "Variables d'environnement".
•Dans la partie basse "Variables système" de la nouvelle fenêtre sélectionner la ligne avec "Path" et clique sur "Modifier".
•Dans la nouvelle fenêtre cliquer sur "Nouveau" et ajouter le chemin de votre Python, par exemple C:\\Users\\Utilisateur\\AppData\\Local\\Programs\\Python\\Python311\,
•Cliquer sur le bouton "Déplacer vers le haut" pour faire monter votre nouvelle ligne avant C:\Windows\system32.
Exemple d'exécution de l'interpréteur "py" accessible dans le path :
D:\tmp>py
Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 22:45:29) [MSC v.1916 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 2+3
5
>>> quit()
J'ai tapé 2+3 qui a été exécuté puis quit() pour sortir de cet interpréteur.
Un programme python s'écrit dans un fichier avec l'extension ".py", par exemple le fichier bonjour.py qui contient la ligne suivante :
print("Bonjour tout le monde.")
On exécute ce programme python en tapant dans une invite de commande :
>python bonjour.py
et là on n'obtient que le résultat de ce programme : Bonjour tout le monde.
Lancement script par double clic
Quand on fait un double clic sur un fichier.py il faut savoir ce qu'on désire :
•ouvrir un éditeur de texte pour éditer le script
•appeler l'interpréteur python pour l'exécuter
Comme, avec le clic droit on peut choisir "ouvrir avec un éditeur", on peut réserver le double clic pour l'exécuter avec l'interpréteur Python. Pour cela on associera les fichier d'extension .py à cet interpréteur.
Pour obtenir ce comportement, on peut procéder comme suit dans l'explorateur:
•faire un clic droit sur un fichier .py,
•puis choisir "Ouvrir avec",
•puis en bas "Choisir une autre application",
•cocher "Toujours utiliser cette application pour ouvrir..."
•puis en bas scroller et choisir "Plus d'applications",
•puis en bas scroller et choisir "Rechercher une autre application sur ce pC",
•et enfin sélectionner son application en la recherchant avec l'explorateur qui vient de s'ouvrir.
Si on fait un double clic sur le fichier bonjour.py dans l'explorateur de fichier, il ne se passe rien. En fait, on ne voit rien car une fenêtre console a été ouverte, python bonjour.py y a été exécuté, le message Bonjour tout le monde y a été écrit, puis la console s'est refermée avant qu'on ait le temps de la voir. Pour s'en assurer, il suffit de faire un fichier bonjour2.py contenant :
print("Bonjour à tous")
s = input("Fini?")
ce qui bloquera l'exécution après le print en attente de notre frappe, qui lorsqu'on tapera la touche Entrée sera acquise et produira la fin d'exécution du script et la fermeture de la console.
Dans une invite de commande, la commande python offre de nombreuses options, dont les plus simples sont :
•Exécuter un script python :
>python toto.py
•Version de python :
>python -v
•Aide sur la commande :
>python ?
>python -h
>python --help
•Exécuter une ligne de code python
>python -c "print('Hello everybody!')"
•Exécuter un module python
>python -m ????
•Ouvrir l'interpréteur dans une console :
>python
Taper quit() pour terminer.
Les programmes python qui sont lancés par Pythonw.exe ne font aucune entrée/sortie dans la console contrairement à Python.exe.
Pour appeler l’interpréteur :
>python
>>>
Pour quitter :
>>>quit(), exit() ou CTRL+Z
Les scripts ordinaires, modules, bibliothèques externes sont simplement importés dans le script courant (ou l'interpréteur) par la commande import.
Dans le script importé les commandes de niveau racine sont normalement exécutées, comme si elles étaient écrites dans le script appelant (généralement, il n'y en a pas dans les bibliothèques).
Le module math (qui offre les fonction cos, sin, ceil, fabs...) est accessible en standard. Ceux qui ne le sont pas doivent être installés par l'utilitaire pip.
Un module accessible est rendu disponible dans le script par la commande import comme ceci :
import math
Ensuite, les fonctions intérieures au script ou module sont accessibles via un nom de la forme module.nomfonction. D'où pour la fonction cos dans le module math :
print(math.cos(1)) # la function print est quand à elle directement disponible
Pour ne pas avoir à taper le nom math on peut faire :
from math import cos, sin
print(cos(1))
ou pour accéder directement à toutes les fonctions de 1er niveau :
from math import *
print(atan2(1,1))
Je déconseille cette pratique car ensuite pour les fonctions qui avoir le même nom dans divers module, on ne sait plus quelle fonction est utilisée. Il faut mieux utiliser un raccourci, comme ceci :
import numpy as np
print(np.cos(1))
On verra plus loin que numpy est un module qui remplace le module math.
On peut également utiliser un alias. Supposons le script fibo.py suivant :
# Fibonacci numbers module
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
On peut exécuter ses fonctions comme suit :
1.import fibo
fibo.fib(10)
2.import fibo
truc = fibo.fib #Et oui on peut créer un alias de n'importe qu'elle fonction
truc(10)
3.from fibo import fib2
fib2(10) # Evite de devoir écrire fibo.fib2(10)
4.from fibo import *
fib(10) # Evite de devoir écrire fibo.fib(val) ou fibo.fib2(val)
5.import fibo as ff
ff.fib2(10) # On utilise un alias du nom du module
6.from fibo import fib2 as f2
f2(10) #On utilise un alias sur fib2
7.ETC.....
•Si un module B importe un module C, il accède partout aux fonctions du module C
•Mais si l'importation de C est effectuée dans une fonction de B, les services de C ne sont accessibles que dans la fonction.
•Si le module B est importé dans le module A, les services de C ne seront pas accessibles dans A, sauf si A importe aussi B.
ATTENTION :
•from module import var ⇒ crée une nouvelle variable var dans le namespace du module courant, initialisée avec la valeur de module.var au moment de l'import.
•import module ⇒ importe le module entier : les noms comme module.var font toujours référence à l’original.
C'est une fenêtre qui offre une console Python. A priori le répertoire de travail offert est celui d'intallation du Python de cet IDLE, ce qui n'est pas bien pratique. Pour vérifier taper :
>>>import os
>>>print(os.getcwd())
C:\Users\Utilisateur\AppData\Local\Programs\Python\Python311
Pour changer de répertoire courant :
>>> os.chdir ('D:\\Tmp')
print(os.getcwd())
d:\temp
Pour placer par défaut le répertoire de travail à l'endroit de son choix, le plus simple est de le faire dans les propriétés du raccourci de lancement qui se trouve sur le bureau. Faire un clic droit sur le raccourci et choisir Propriétés.
Mettre dans "Démarrer dans le repertoire de son choix.
Si la librairie n'est pas standard, il faut la télécharger.
L'installation de Python vient avec un installateur de packages (librairies) qui s'appelle pip. (Python Installateur Package). Pour ajouter une librairie en provenance de https://pypi.org, par exemple totolib, il suffit de taper dans une fenêtre dos les commandes :
>python -m pip install --upgrade pip
en premier lieu pour mettre pip à jour, puis
>python -m pip install --upgrade totolib
ou plus simplement (python -m n'est pas nécessaire) :
>pip install --upgrade totolib
On obtient la liste des librairies installées en tapant :
>pip list => liste des librairies installées
On désinstalle un paquet en faisant
>pip uninstall -totolib
Les librairies suivantes intéressantes sont généralement dans le package installé par défaut :
•numpy : manipulation des matrices ou tableaux multidimensionnels ainsi que des fonctions mathématiques opérant sur ces tableaux
•scipy : librairie pour l'optimisation, l'algèbre linéaire, les statistiques, le traitement du signal, le traitement d'images (style Matlab/octave), compatible numpy.
•matplotlib : librairie pour tracer et visualiser des données sous formes de graphiques, compatible numpy et scipy.
Mais aussi :
•tkinter : librairie pour créer des interfaces graphiques utilisateur avec des fenêtres, boutons, etc. (n'est pas dans les package : installée par défaut)
>python -m tkinter => exécute une petite appli graphique tkinter.
•pygame librairie graphique et interface clavier, souris, joystick ... construite au-dessus de la SDL.
•tensorflow : librairie pour les réseaux neuronaux
Le nouvel éditeur de code gratuit de Microsoft "Visual Studio Code" est plus pratique que l'IDLE Python.
Ne pas confondre "Visual Studio Code" avec "Visual Studio" tout court qui est un environnement de programmation très lourd, surtout dédié C/C++, C#, .NET
Un tutoriel pour utiliser cet éditeur avec Python se trouve ici : https://code.visualstudio.com/docs/python/python-tutorial
Installer l'IDE Visual Studio Code (VSCode) : Télécharger l'installateur depuis : https://code.visualstudio.com/docs/?dv=win et l'installer (éventuellement dans un répertoire plus facile à localiser que celui qui est proposé). [Tuto utilisation de VSCode : https://code.visualstudio.com/docs?start=true ] .
Faire un test de Python avec VSCode :
•menu File/new
•Dans le fenêtre d'édition taper :
print("Hello World")
•puis menu File/Save choisir un répertoire et donner comme nom "hello.py"
L'éditeur doit appliquer une coloration syntaxique au texte.
•Si un warning indique "linter pylint is not installed", clique sur "install it" : c'est un logiciel de vérification qualité du code Python (facultatif ?).
•Pour exécuter hello.py depuis VSCode, faire un clic droit dans la fenêtre d'édition et choisir "Run Python file in Terminal"., ou menu Run/Run without debugging ou encore CTRL+F5.
Pour exécuter ce fichier hello.py, directement (sans VSCode, ni rien d'autre), ouvrir l'explorateur windows, aller dans le répertoire ou se trouve le fichier "hello.py", taper "cmd" (sans les guillemets) dans la barre d'adresse de l' explorateur (là ou il y avait le chemin du répertoire) et faire Return. Une invite de commande s'ouvre directement dans ce répertoire. Taper "py hello.py" (sans les guillemets) et Return dans la fenêtre.
IMPORTANT : L'interpréteur Python utilisé nativement dans VSCode est celui de Windows c'est-à-dire (dans mon cas) : "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Python37_64\\python.exe". Cet interpréteur ne va pas trouver les librairies installées depuis python.org. Pour cela, il faut indiquer à VSCode d'utiliser l'interpréteur de Python.org ce qui est fait en utilisant une commande adresssée à VSCode, pour cela taper CTRL+MAJ+P (ou menu Help Show all commands) ce qui ouvre la liste des commandes, commencer à taper Python et dans la liste déroulante choisir Python: Select Interpreter et là il doit y avoir le bon, où alors écrire le chemin complet dans "Enter interpreter path".
# le caractère # précède un commentaire jusqu'à la fin de la ligne (sauf dans un string).
Pour insérer plusieurs lignes, il faut les encadrer par un triple guillet double : """ """, comme ceci :
""" labyr_00.py :
Jeu de labyrinthe
blablabla
"""
Indentation des blocs ou sous-blocs :
Pour définir un bloc ou sous-bloc de code il faut et il suffit de l'indenter par rapport à la ligne précédente par un ou plusieurs espaces avec toujours le même nombre d'espaces pour tout le sous-bloc. On peut utiliser un ou plusieurs tabs à condition que l'éditeur les convertisse en espaces car il ne faut pas mélanger les caractères tab et espace.
Une ligne du code primitif, c'est-à-dire appartenant niveau de départ ne doit pas avoir d'espace ou tab en tête de ligne.
Continuation de ligne
Le caractère \ suivi d'un retour ligne peut être utilisé à tout moment pour continuer à la ligne suivante comme s'il n'y avait pas de retour ligne.
On appelle script un programme principal (généralement écrit dans un fichier). Dans un fichier contenant du python, il peut y avoir des fonctions (parties de code débutant par :
def toto():
....
et une partie dite de script dont certaines lignes ne sont dans aucune fonction et débutent directement à gauche sans aucune indentation. S'il n'y a aucune partie de script dans le fichier, le fait de l'activer avec les commandes py, python ou pythonsw ne produira aucun effet. Par contre s'il y a une aprtie de script, elle sera exécutée, appelant éventuellemnt les fonctions du fichier ou d'autres fichires.
Les commandes exit() ou quit() provoquent la sortie de l'interpréteur Python et son abandon. Pour sortir prématurément d'un script sans provoquer la sortie de l'interpréteur on peut utiliser sys.exit() ce qui suppose que l'on ait fait un import sys auparavant :
import sys
...
sys.exit()
...
Pour sortir d'une fonction on utilisera tout simplement l'instruction return.
Remarque : sys.executable fournit le nom du programme interpréteur utilisé :
print(sys.executable) ==>
C:\Users\Utilisateur\AppData\Local\Programs\Python\Python311\pythonw.exe
En python, la déclaration d'une variable se fait par son initialisation qui va déterminer son type :
>>> x = 2
>>> x
2
Une zone mémoire est affectée pour loger un élément de type entier. Dans cette zone la valeur 2 est codée. Dans la liste des variables gérées par l'interpréteur le nom "x" est ajouté et on le fait pointer cette variable sur la zone mémoire qui contient l'entier 2.
c, d, e = 5, 10, 15 ==> c => 5; d => 10; e => 15.
int, float, decimal.Decimal, Fraction et gestion des nombres complexes en collant le caractère suffixe j ou J à fin de la partie imaginaire du nombre (ex : 2+3.1j ou 2+3.1J). Comme en basic , il n'est pas nécessaire de déclarer le type des variables, le typage se fait dynamiquement par contexte.
Les int ont une précision illimitée. Les float correspondent aux double en C. Je n'ai pas pratiqué les decimal.Decimal et Fraction.
Arithmétiques :
+ - * addition, soustraction, multiplication
/ division flottante
// division entière
% reste de la division entière
** puissance flottante
La variable _ contient la valeur de la dernière expression imprimée. Ne pas lui donner de valeur sous peine de perturber son fonctionnement.
Logique et opérateurs logiques : or, and et not
Il existe 2 quantités logiques qui sont True et False. On les combine avec les opérateurs or, and et not.
Opérateurs de comparaison :
Les opérateurs de comparaison suivants renvoient comme résultat la valeur logique True ou False :
<, >, ≤, ≥, ==, != ou <>, is, is not.
x is y renvoie True si x et y représentent le même objet.
Les strings sont des tableaux de caractères.
x = "moto" => x[0] c'est "m".
len(x) ==> 4 : le nombre d'éléments du tableau.
Les caractères, indices négatifs :
Un caractère est un string de longueur 1. On accède aux caractères d'un string, de gauche à droite par un indice i variant de 0 à L-1, et de droite à gauche par un indice r variant de -1 à -L.
Exemple : str = 'python'
•str[0] => 'p'
•str[1] => 'y'
•str[5] => 'n'
•str[-1] => 'n'
•str[-2] => 'o'
•str[-6] => 'p'.
Les strings sont immutables : str[2] = 'i' => erreur !
Les strings peuvent initialisés par un texte entre guillements 'simples' , "doubles", voire '''triples simples''' et """triples doubles""".
Dans une chaine entre guillemets simples telle que 'abc' le caractère \ peut être utilisé pour rendre le caractère ' qui le suit ordinaire (ex : chaine = 'Aujourd\'ui').
Dans une chaine entre guillemets doubles telle que "abc" le caractère ' est ordinaire. Et réciproquement pour les chaines 'abc'.
La caractère \ est également utilisé pour protéger les caractères de commande d'impression comme \n pour commander une nouvelle ligne. Dans l'affichage de la valeur d'une variable string, les caractères \n sont affichés sans être interprétés. Par compte, si la variable est imprimée par la fonction print(...), une nouvelle ligne est imprimée à la place des caractères \n.
Les triples guillemets (simples ou doubles) permmettent d'écrire un texte sur plusieurs lignes, avec inclusion automatique des nouvelles lignes sans avoir à mettre les caractères \n. Exemple :
"""une ligne
une autre ligne
une dernière ligne"""
et si on met \ sans rien derrière en fin d'une ligne, cela supprimera le retour ligne qui le suit.
Un string précédé du caractère préfixe r est un raw strings où le caractère \ est conservé : il perd sa spécicificité de protection :
r"Dans cette chaine le caractère \ est conservé"
str = 'python'
•str[:2] => 'py'
•str[2:] => 'thon'
•str[2:5] => 'tho'
•str[-2:] => 'on' (à l'envers en partant de la fin)
Les espaces entre des strings littéraux sont ignorés.
•str1 + str2 : permet de concaténer str1 et str2
•int * str : permet de dupliquer str int fois :
3 * 'un string' => 'un stringun string un string'
On peut ajouter un string dans un string à la place des caractères %s, en faisant suivre ce string de l'opérateur % suivi du texte à insérer. Exemple :
texte = "Bonjour %s, comment vas-tu ?"
newText = texte % "michel"
Le résulta sera : "Bonjour Michel, comment vas-tu ?"
Si on met plusieurs %s pour plusieurs texte, par exemple trois %s comme ici :
texte = "Bonjour %s et %s, avez vous vu % ?", les 3 strings de remplacement doivent être mis entre (..). Exemple :
newText = texte % ("Pierre", "Paul", "Thomas") donnera comme résultat :
"Bonjour Pierre et Paul, avez vous vu Thomas ?"
: La conversion de string en type simple n'est pas toujours automatique. Certaines fonctions attendant un type précis, on doit parfois convertir explicitement vers ce type précis avec les fonctions de conversion suivantes : int(), float(), str(), ..
La méthode format() permet de formater divers champs numériques repérés par {unNom}, ou son ordre {index}, ou dans l'ordre naturel {}. Exemples :
txt1 = "Mon nom {lenom}, J'ai {lage} ans".format(lage = 36, lenom = "John")
txt2 = "Mon nom {1}, J'ai {0} ans".format(36, "John")
txt3 = "Mon nom {}, J'ai {} ans".format("John",36)
La quantité entre accolades peut être suivie d'un ":" suivi d'une information de formatage. Par exemple :
•{val:10} => la valeur val sera écrite sur 10 caractères
•{val:10.2} => la valeur val sera codée avec 10 caractères dont 2 après la virguele en format E style "915.23E+02"
•{val:10.2f} sera codé " 91523.78"
Ce sont des trings qui offrent un systême de formatage avancé. Ils sont très utiles pour faire des impressions formattées :
Une simplification de
"Mon nom est {}, J'ai {} ans".format("John",36)
est simplement obtenue par :
f"Mon nom est {'John'}, J'ai {36} ans".
Remarquer le caractère f devant les guillemets. A l'intérieur de l'accolade on met directement l'expression qui sera évaluée et convertie en string. Dans l'accolade, on peut faire suivre la valeur à évaluer et convertir en string de ":" puis d'un format du type 7.2f pour sécifier 7 caractères en tout, dont 2 après le point en format flottant ordinaire, comme par exemple :
f"22/7 est une approximation de pi qui vaut {(22/7):6.4f}." ce qui génèrera :
'22/7 est une approximation de pi qui vaut 3.1429.'
Dans 7.2f, si le nombre comporte moins de 7 caractères comme 3.14, il seraont précédés de 3 espaces. On écrira 07f.2 si on veut faire précéder par des 0 => 0003.14
Si 7 est absent ou inférieur au nombre nécessaire, le nombre nécessaire est utilisé.
La méthode str.join(iterable) est assez bizarre. Elle construit une chaine en concatenant tous les strings issus de l'objet iterable séparés par le string str. Exemple :
"AB".join("abc") ==> "aABbABcAB". Dans le cas ou l'objet iterable est un dictionnaire les strings utilisés ne sont pas les valeurs, ce sont les clés !
Attention : dans os.path.join(...) ce n'est pas cette méthode join qui est utilisée mais une surcharge.
La méthode len(x) donne le nombre des éléments.
Un tuple est une collection d'éléments divers qui est immutable : On ne peut pas modifier, ajouter ou supprimer des éléments après la création, même si un des éléments interne est une liste mutable :
Un tuple est crée entre des parenthèses.
toto = (1, "baki", 1+3j, "z")
On accède aux éléments avec des crochets :
toto[2] ==> 1+3j
toto[1][3] ==> 'i'
Toute affectation produit une erreur.
List est une collection d'éléments divers qui est mutable (on peut ajouter ou supprimer des éléments après la création et modifier ceux qui sont mutables).
Une liste est crée par le constructeur list() ou en mettant des éléments entre crochets :
toto = [1, "baki", 1+3j, "z"]
toto[0] = "cocou" => 1 est remplacé par "cocou"
toto[1][2] = 'm' produit une erreur car le string 'baki' n'est pas mutable.
toto[1:2] = [28,'tu'] ==> toto => [1, 28, 'tu', 'z']
Un élément peut être une autre liste (et ainsi de suite..)
Pour initialiser une liste mutable de caractères on peut faire :
list1 = [' ' for i in range(5)]
Ici on pourra faire list1[4] = 'e'
Pour initialiser une liste de liste mutable de caractères on peut faire :
list2 = [[' ' for j in range(3)] for i in range(8)]
Ici on pourra faire list2 [7][2] = 'm'
Méthode des listes :
append : toto.append('tt') => [1, 28, 'tu', 'z', 'tt']
remove : toto.remove("tu") => [1, 28, 'z', 'tt']
extend : a = [1,2,3]; a.extend([4, 5]); print(a) =>[1, 2, 3, 4, 5]
del : del(a[2]) => print(a) =>[1, 2, 4, 5] #supprime l'élément d'indice donné
del(liste[0]) # On supprime le premier élément
del(liste[–1]) # On supprime le dernier élément.
del(liste[1 : 3]) # On supprime les éléments d’indices 1 à 3-1
len(toto) => nombre d'éléments (du premier niveau) de la liste.
Très proche du type list, le type array (les tableaux) est fourni par le module numpy. Ces types sont plus puissants que les listes car ils peuvent être manipulés par de plus nombreuses fonctions. Par exemple ont peut multiplier tous les éléments d'un tableau de nombres par un nombre. Par contre ils doivent être déclarés par numpy.array(). Il existe aussi des tableaux array.array() qui sont plus restrictifs, ils ne peuvent contenir qu'un seul type d'élément qui est spécifié lors de la déclaration.
Nous avons vu qu'on accède à un élément à l'aide d'index entre crochets comme dans toto[1][2].
On accède à tous les éléments :
•dans le sens direct, du premier au dernier par x[i] avec i variant de 0 à len(x) - 1.
•en sens inverse, du dernier au premier par x[i] avec i variant de -1 à -len(x).
On peut vérifier que x[0] == x[-len(x)] et que x[-1] == [x[len(x)-1] .
Les tuples,listes et tableaux doubles peuvent être adressés avec des doubles crochets [i][j], mais les tableaux offrent également l'accès en [i, j].
Il est utilisé pour générer des index, comme ceci x[i:k], est presque identique à celui de Matlab/Octave. Il est décalé de 1, puisque dans Matlab/Octave l'indice varie de 1 à length(x) alors que dans Python il varie de 0 à len(x)-1. De plus dans Python k-i éléments sont générés alors que dans Matlab/Octave leur nombre est égal à k-i+1.
x[i:k] génère une nouvelle liste comportant tous les éléments de x[i] à x[k-1].
•Si i est absent il est pris égal à 0 => la liste générée débute par le premier élément de x
•Si k est absent il est pris égal à len(x) => la liste générée finit par le dernier élement de x (d'indice len(x)-1).
•Si i et k sont absents, la liste générée est identique à la liste originale.
On l'utilise beaucoup pour extraire des portions de string.
Slicing étendu à 2 double points "ided : ifin : pas"
a:b:k sélectionne la séquence d'indices a, a+k, a+2k, ... tant que a+nk < b
Ainsi ::3 sélectionne 0, 3, 6, 9 tant que inférieur à len(objet)
tata = toto # tata est un alias sur toto. Toute modification de toto est répercutée sur tata. Les variables toto et tata pointent sur le même objet en mémoire
titi = toto[:] # titi est une copie complète de toto, totalement indépendante de toto.
Les noms utilisés pour identifier les variables suivent les conventions suivantes :
•Ils ne doivent contenir que les lettres A-z, les chiffres 0-9 et le caractère souligné _.
•Ils doivent commencer par une minuscule ou un caractère souligné _.
•Un nom débutant par un caractère souligné _ concerne une variable _privee (n'est pas importé par import par exemple),
•Un nom débutant par deux caractères soulignés __ concerne une variable __fortementprivee
•Un nom débutant et finissant par deux caractères soulignés __ concerne une __methodespeciale__ ou un __objetspecial__ du système.
•Un nom de classe commence par une Majuscule.
Il y a deux objets spéciaux __name__ et __main__ très utiles pour rajouter du code dans un module (fichier .py contenant un script ou/et des fonctions) afin de tester ses fonctions. Dans ce cas on met le code suivant :
# Pour tester le module
if __name__ == "__main__":
... # code de test
....
__name__ est un string dont la valeur vaut __main__ quand le code est appelé en tant que script et qui vaut le nom du module (sans le .py) quand c'est une de ses fonctions qui est appelée.
Exemple de code rajouté dans fibo.py pour tester ce module par la ligne de ommande suivante :
>python fibo.py 10
On met à la fin de fibo.py le code suivant :
if __name__ == "__main__":
import sys
# on exécute fib() avec l'argument de la ligne de commande
fib(int(sys.argv[1]))
Le nom du fichier en cours d'exécution est fourni par :
fs = __file__
mais cela peut produire NameError si __file__ n'existe pas. Il est conseillé de faire :
fs = globals().get('__file__', '')
qui renverra le deuxième string ('') si __file__ n'existe pas. On peut même ajouter strip() pour supprimer les éventuels balncs avant et après :
fs = globals().get('__file__', '').strip()
Pour avoir le répertoire de ce fichier on fera :
repf = os.path.dirname(os.path.abspath(fs))
où fc = os.path.abspath(fs) est le chemin complet avec toute la hiérachie de répertoires et où :
repf = os.path.dirname(fvc) est le chemin sans le nom du fichier.
On peut reconstituer le nom complet en faisant
fc = os.path.join(repf, fs)
Ici la méthode join est spécifique et ajoute les séparateurs nécessaires.
fich=open("nomfichier",'r") #ouvrira le fichier en lecture
ligne=fich.readline() #transfère la ligne lue dans la variable ligne
contenu=fich.read() #transfère le contenu de tout lefichier dans la variable contenu
fich.close() #On ferme le fichier
fich=open("nomfichier","a") #ouvrira le fichier en ajout d'écriture
fich.write("Contenu à ajouter") #ajout du contenu à la fin du fichier
fich.close()
etat = fich.closed #True ou false suivant que le fichier est fermé ou ouvert.
Pour les boites de dialogue d'ouverture de fichiers voir le paragraphe 5.8.
Pour recevoir des noms de fichier en argument d'un script, on mettra ce code à la fin :
if __name__ == "__main__":
# ligne précédente pour le cas où le fichier ne contient que des fonctions et qu'on veuille y ajouter ce bout de script
import sys
files = sys.argv[1:] # Arguments 1 à la fin (0 est le nom du scrip)
.....
L'instruction with en Python est utilisée dans la gestion des exceptions pour rendre le code plus propre et beaucoup plus lisible. Il simplifie la gestion des ressources communes telles que les flux de fichiers. Observez l'exemple de code suivant sur la façon dont l'utilisation de l'instruction with rend le code plus propre.
# file handling
# 1) without using with statement
file = open('file_path', 'w')
file.write('hello world !')
file.close()
# 2) without using with statement
file = open('file_path', 'w')
try:
file.write('hello world')
finally:
file.close()
filter_none
brightness_4
# using with statement
with open('file_path', 'w') as file:
file.write('hello world !')
Notez que contrairement aux deux premières implémentations, il n'est pas nécessaire d'appeler file.close() lors de l'utilisation de l'instruction with. La déclaration de with elle-même garantit l'acquisition et la libération appropriées des ressources. Une exception pendant l'éxécution du file.write() dans la première implémentation peut empêcher le fichier de se fermer correctement, ce qui peut introduire plusieurs bogues dans le code, car de nombreux changements dans les fichiers ne prennent effet que lorsque le fichier est correctement fermé.
La deuxième approche de l'exemple ci-dessus prend en charge toutes les exceptions, mais l'utilisation de l'instruction with rend le code compact et beaucoup plus lisible. Ainsi, l' instruction with permet d'éviter les bogues et les fuites en s'assurant qu'une ressource est correctement libérée lorsque le code utilisant la ressource est complètement exécuté. L'instruction with est couramment utilisée avec les flux de fichiers, comme indiqué ci-dessus et avec les verrous, les sockets, les sous-processus et les telnets, etc.
Prise en charge de l'instruction «with» dans les objets définis par l'utilisateur
Il n'y a rien de spécial dans l'instruction open() qui la rend utilisable avec l'instruction with et la même fonctionnalité peut être fournie dans les objets définis par l'utilisateur. Une déclaration with à sur vos objets garantira que vous ne laisserez jamais aucune ressource ouverte.
Pour utiliser l'instruction with dans une classe définie par l'utilisateur, il faut ajouter les méthodes __enter__() et __exit__() dans les méthodes de la classe. (voir documentation ??)
print (proche du print basic).
print(2, " + " , 3 , " = ", 5, " n'est-ce pas ?") => 2 + 3 = 5 n'est-ce pas ?
Pour remplacer le retour ligne par un espace, terminer les arguments par ,end=' ')
input : mon_age=input("Quel est votre âge ? ")
Attention : input renvoie un string !
pass : instruction vide (rien à faire : idem instruction assembleur noop : no operation). Permet de rendre certaines parties du code plus lisibles.
id(var) : renvoie l'identificateur de l'objet pointé par var. Deux variables qui pointent le même objet on le même identificateur.
dir(object) : Liste des fonctions applicables à l'objet. Voir paragraphe 3.15.1
is est un opérateur qui renvoie True si les deux opérandes pointent le même objet :
x is y ne renvoie True que si x et x pointent le même objet qui a été affecté tour à tour à x et à y.
len(obj) : longueur d'un string, d'une liste, d'un tableau : len('toto') => 4
range : range(deb, fin, pas) : séquence itérable => deb, deb+pas, deb+2*pas, ... <= fin
si deb absent, deb = 0, si pas absent pas = 1.
list : Construit une liste à partir d'objet itérables
list(range(4)) => [0, 1, 2, 3]
Générateur aléatoire : (import random)
random.randrange(debut, fin) => nb aléatoires dans [debut : fin-1]
random.randrange(fin) => nb aléatoires dans [0 : fin-1]
Les exécutions des sous-blocs sont conditionnées par les instructions :
if <condition> :
pass
elif <condition> :
pass
else :
pass
Remarque: Chaque condition se termine par un ":". Les instructions elif et else sont facultatives.
•Les sous-blocs conditionnels qui suivent ces instructions sont simplement délimités par une indentation supplémentaire.
•Le sous-bloc s'achève dès que l'indentation revient au niveau qui est celui de l'instruction if, elseif ou else.
La condition est une expression quelconque dont le résultat doit être True ou False.
Exemple :
>>> if x < 0 :
... x = 0
... print('négatif annulé')
... elif x == 0 :
... print('nul')
... elif x == 1:
... print('un')
... else:
... print('plus')
...
Il est possible de mettre une if sur une seule ligne comme ceci :
a = 1
b = 2
if a== 1: print("a = 1"); print("égal")
if a!= 1: print("a = 1"); print("not égal")
if b == 2: print("b= 2")
print("Fini")
Sortie :
a = 1
égal
b= 2
Fini
Le calcul conditionnel
condition ? valeur_si_vrai : valeur_si_faux
des langages C/C++, java, c#... existe en Python avec la syntaxe suivante :
valeur_si_vrai if condition else valeur_si_faux
Exemple :
n = 5
print(f"{n} est {'pair' if n%2 == 0 else 'impair'}")
=> 5 est impair
La quantité en rouge est évaluée à la valeur 'impair'.
for w in <sequence> :
sous-bloc
Remarquer le ":" à fin de la ligne de l'instruction for. La séquence est une liste, une chaine de caractère, un objet itérable.... La variable w (dite itérateur ou curseur) prend tour à tour la valeur de chaque élément de la liste et le sous-bloc est exécuté avec cette valeur. Exemple :
>>> mots = ['chat', 'chien', 'poisson']
>>> for w in mots:
... print(w, "a ", len(w), " lettres")
...
chat a 4 lettres
chien a 5 lettres
poisson a 7 lettres
Autre exemple :
>>> for w in range(len(mots)):
... print(w, mots[w])
...
0 chat
1 chien
2 poisson
Remarque : Le corps du for peut tenir sur une ligne :
w = [1, 2, 3, 4]
s, s2 = 0, 0
for x in w: s += x; s2 += x*x
print(s, s2)
=> 10 30
while condition :
sous-bloc
Instruction continue : permet de sauter la fin du sous-bloc et passer à l'itération suivante.
Instruction break : permet de sauter la fin du sous-bloc et sortir de la boucle for.. while
Instruction else : Placée après le sous-bloc du for : Son sous-bloc sera exécutée si aucun break n'a interrompu le traitement de la boucle for.
Instruction pass : Elle ne fait rien. Peut être utilisée n'importe où (créer une classe vide par ex.)
Il n'y a pas de SWITCH CASE en python.
def fonction(arg1, arg2, ...) :
sous-bloc de la fonction
Remarquer le ":" à fin de la ligne de l'instruction def.
La fonction est terminée dès qu'une instruction est mise au même niveau d'indentation que le mot clé def (qui débute la définition de la fonction). La fonction se termine à la ligne qui précède cette instruction.
Les arguments sont passés par valeur.
Généralement on met en première ligne du sous-bloc un "string" qui indique ce que fait la fonction. Exemple :
def fibo(n):
"""Renvoi la suite de Fibonacci de 0 à n."""
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
>>> fibo(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
Dans un fichier une fonction peut être définie à n'importe quel endroit, mais avant toute instruction qui l'appelle.
Les variables définies à l'intérieur des fonctions sont locales. Elles ne sont pas visibles de l'extérieur de la fonction.
Les variables définies au niveau zéro (main) sont globales et visibles dans les fonctions.
Si une variable globale est modifiée à l'intérieur d'une fonction, la modification n'est visible que dans la fonction. Pour qu'elle soit visible à l'extérieur, il faut auparavant la déclarer global à l'intérieur de la fonction (quelle existe déjà ailleurs ou non).
a, b = 1, 1
def test():
global a
a += 1; b = 2
print(a,b)
test()
print(a,b)
Résultat :
2 2
2 1
Dans la fonction test() a est augmenté de 1 à 2, d'où le résultat 2,2 et à l'extérieur après l'appel de la fonction a garde la nouvelle valeur 2, mais b conserve l'ancienne valeur 1.
Considérons les scripts pythons suivants :
journal.py :
s = str("0 ")
globale.py :
def do_externe():
from journal import s
global s
s += "4 "
print("Fin do_externe :",s)
scope.py :
def scope_test():
import globale
global s
def do_local():
global s
s += "3 "
print("Fin do_local :",s)
s += "2 "
print("Avant do_local :", s)
do_local()
print("Avant do_externe :", s)
globale.do_externe()
print("Apres do_externe :", s)
from journal import s
s += "1 "
scope_test()
print("Apres scope_test :", s)
L'exécution :
>>> import scope
Avant do_local : 0 1 2
Fin do_local : 0 1 2 3
Avant do_externe : 0 1 2 3
Fin do_externe : 0 4
Apres do_externe : 0 1 2 3
Apres scope_test : 0 1 2 3
>>>
Le variable s du module journal est importé dans le module globale où elle est déclaré global dans la fonction do_externe.
elle est également importée dans la racine du module scope où elle est initialisé à "1".
Dans la fonction scope_test la variable s est déclaré global ainsi que dans la sous_fonction do_local.
A la racine de scope, il y a appel de scope_test qui concatène "2 " et imprime :
Avant do_local : 0 1 2
puis appelle do_local qui concatène "3 " et imprime :
Fin do_local : 0 1 2 3
puis imprime :
Avant do_externe : 0 1 2 3
puis appelle globale.do_externe qui concatène "4 " et imprime :
Fin do_externe : 0 4
puis :
Apres do_externe : 0 1 2 3
et enfin en sortie de scope_test le niveau zéro imprime :
Apres scope_test : 0 1 2 3
On constate que le module globale utilise la valeur initiale de s créée dans journal, car c'est elle qui est importée et pas sa référence.
Si on veut utiliser le même string partout, il modifier les scripts comme ceci :
globale.py :
import journal
def do_externe():
journal.s += "4 "
print("Fin do_externe :", journal.s)
scope.py :
import journal
import globale
def scope_test():
journal.s += "2 "
print("Avant do_local :", journal.s)
def do_local():
journal.s += "3 "
print("Fin do_local :", journal.s)
do_local()
print("Avant do_externe :", journal.s)
globale.do_externe()
print("Apres do_externe :", journal.s)
journal.s += "1 "
scope_test()
print("Apres scope_test :", journal.s)
Résultat :
>>> import scope
Avant do_local : 0 1 2
Fin do_local : 0 1 2 3
Avant do_externe : 0 1 2 3
Fin do_externe : 0 1 2 3 4
Apres do_externe : 0 1 2 3 4
Apres scope_test : 0 1 2 3 4
>>>
ATTENTION :
•from module import var ⇒ crée une nouvelle variable var dans le namespace du module courant, initialisée avec la valeur de module.var au moment de l'import.
•import module ⇒ importe le module entier : les noms comme module.var font toujours référence à l’original.
Les arguments nommés sont des arguments de fonction, facultatifs, qui sont précédés d'un nom pour être identifiés (voir exemple ci-dessous section 3.16.1)
Les arguments non nommés sont dits positionnels. Leur présence est obligatoire, en tête de liste des arguments et ils doivent être dans le même ordre que dans la définition de la fonction.
Les arguments nommés peuvent être absent lors de l'appel, ils prennent alors la valeur par défaut qui figure en argument dans la définition de la fonction. Dans l'appel, leur présence est facultative et leur ordre est quelconque, après les arguments positionnels.
On peut passer une liste d'arguments à une fonction en la représentant par un argument étoilé, comme ceci :
def totargs(*args):
res = 0
for v in args:
res += v
return res
print(totargs(5,4,3,2,1))
A l'intérieur de la fonction l'argument étoilé est traité comme un tuple.
Il existe un raccourci pour des fonctions simples qui peuvent se résumer à une seule expression. (elle peut avoir plusieurs arguments).
Par exemple la fonction suivante qui renvoie true si l'objet x passé en argument a sa propriété name égale au string "Cooler" :
def is_cooler(x):
return x.Name == "Cooler"
peut être écrite sous forme de fonction lambda, comme ceci :
lambda x: x.Name == "Cooler"
Si une fonction Find(callback) prend en argument une callback(x) qui reçoit en argument des objets dont on cherche celui qui à la propriété Name = "Cooler", au lieu d'écrire la fonction is_cooler(x) et de la passer en argument comme ceci Find(is_cooler), on écrira directement :
Find(lambda x: x.Name == "Cooler").
Tout est objet dans Python, même les nombres int les plus simples. Pour connaitre les fonctions qui sont applicables à un élément, il suffit d'appeler la fonction dir() sur cet élément. Exemple :
Liste des fonctions applicables aux objets Python : dir()
>>> dir(0.2)
['__abs__', '__add__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getformat__', '__getnewargs__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__int__', '__le__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__pos__', '__pow__', '__radd__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__round__', '__rpow__', '__rsub__', '__rtruediv__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', 'as_integer_ratio', 'conjugate', 'fromhex', 'hex', 'imag', 'is_integer', 'real']
On obtient la liste de toutes les méthodes que l'on peut utiliser sur l'objet (0.2). Ici les parenthèses sont nécessaires pour délimiter l'objet que l'on considère. Exemples :
>>> (0.2).real
0.2
>>> (0.2).imag()
0.0
>>>(0.2).__add__(4)
4.2
>>>(0.2).__ceil__()
1
On remarquera que les fonctions spéciales ne sont généralement pas documentées et pratiquement pas utilisées telles que. Par exemple on additionne simplement avec :
>>>0.2+4
4.2
et on prend le plafond par :
>>>import math
>>>math.ceil(0.2)
1
La fonction type(attr) est très utile pour connaitre le type d'un attribut. La liste des types simples figure section 9.1.
La documentation des langages modernes n'arrivant pas à suivre leur explosion, on utilisera les fonctions suivantes pour palier à ce défaut de documentation :
hasattr(object, attribut) : renvoie true si l'objet possède l'attribut donné (string ou variable pointant un string correspondant au nom de l'attribut).
getattr(object, attribut) : renvoie la valeur de l'attribut
hasattr(object, attribut, value) : modifie la valeur de l'attibut.
Le script suivant est utile pour lister les attributs d'un objet :
for attr in dir(objet):
if not attr.startswith('__'):
try:
print(f"{attr} = {getattr(objet, attr)}")
except:
print(f"{attr} (inaccessible)")
class est le mot clé qui permet de créer de nouveaux objets qui s"utilise comme le mot clé ref pour créer une fonction, mais le nom de la classe n'est suivi de rien, excepté le ":" alors que le nom de la fontion est suivi de "():"
Exemple :
class Eleve:
pass
On déclare un objet de cette classe, simplement comme ceci :
toto = Eleve()
ATTENTION :
Comme dans le cas d'une fonction, on peut écrire
riri = Eleve
mais dans ce cas riri n'est pas un objet, instance de la classe Eleve, mais un alias pour le nom de cette classe.
Dans une classe on mémorise des valeurs et des fonctions. Les valeurs sont appelés des attributs de la classe et les fonctions sont appellées des méthodes de la classe. Exemple :
class Eleve:
nom=""
age = 0
def cequoi():
print("Je suis un élève.")
nom et age sont deux attributs, et cequoi() est une méthode de la classe Eleve.
>>>toto = Eleve()
>>>riri = Eleve()
>>>toto.cequoi()
Je suis un élève
>>>toto.age = 5
>>>riri.age = 6
>>>print(f"toto a {toto.age} ans et riri a {riri.age} ans")
toto a 5 ans et riri a 6 ans
On peut ajouter des attributs à riri, mais ils ne seront pas connus des autres instances de la classe Eleve.
>>>riri.taille = 1.50
Pour qu'une méthode de la classe puisse utiliser les valeurs des attributs de cette instance, il faut utilser une variable qui désigne l'instance en cours. Dans la plupart des langages cette variable pré-existe et s'appelle this. En python il faut la définir dans une méthode spéciale __init__() appelée le constructeur, qui est automatiquement appelée à chaque création d'une instance.
Supposons que l'on crée l'instance :
>>>fifi = Eleve("Fifi", 12)
Cela va appeler le constructeur __init__(nomInstance, "Fifi", 12). ou nomInstance est un nom quelconque utilisé dans le code de la class.
Il n'y a pas que __init__(...), toutes les méthodes définies à l'intérieur de la classe comportent un premier argument qui ne figure pas dans les appels de ces méthodes et qui est l'instance de la classe qui fait l'appel de la méthode en question.
Exemple :
class Eleve:
nom = ""
age = 0
def __init__(this, strNom, valAge):
this.nom = strNom
this.age = valAge
def cequi(inst, str):
print(str+f"Je m'appelle {inst.nom}, j'ai {inst.age} ans")
Le nom de la variable peut-être quelconque. Ici on a utilisé this, puis inst, mais l'usage veut et recommande fortement qu'on utilise self.
Utilisation :
>>>toto = Eleve("Toto",8)
>>>toto.cequi("Coucou : ")
Coucou : Je m'appelle Toto, j'ai 8 ans
Il peut être intéressant d'utiliser des arguments nommés pour modifier les attributs. Exemple
class Eleve:
nom = ""
age = 0
def __init__(this, strNom, valAge):
this.nom = strNom
this.age = valAge
def cequi(inst):
print(f"Je m'appelle {inst.nom}, j'ai {inst.age} ans")
def modifie(self, name=None, age=0):
if name is not None: self.nom = name
if age > 0: self.age = age
>>>toto=Eleve("Toto",23)
>>>toto.modifie(name='Riri')
>>>toto.modifie(age=14)
>>>toto.cequi()
Je m'appelle Riri, j'ai 14 ans
Remarquer qu'on peut utiliser, ou pas, le même nom que l'attribut en nom d'argument.
Remarque :
Le premier argument dans la déclaration de la méthode est toujours le pointeur sur l'instance de l'objet et il y a deux manière d'appeler une méthode :
toto.modifie(age=14) ou Eleve.modifie(toto,age=14)
toto.cequi() ou Eleve.cequi(toto)
Dans la première manière l'argument est inutile et n'est donc pas mis, alors que dans la deuxième il permet de préciser l'instance.
Une classe peut étendre une classe préexistante, par exemple Indivu, en la mettant en argument dans la définition :
class Personnage(Individu):
....
La classe Personnage hérite automatiquement des attributs et méthodes de la classe Individu.
Lors de la définition de la classe, on peut y rédéfinir les méthodes des classes dont il hérite.
Même la classe minimale
class Vide:
pass
hérite de nombreuses méthodes de l'objet minimal Python :
>>>dir(Vide)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
Il peut être intéressant de redéfinir certaines méthodes. Exemples :
•def __init__(self, arg1,...) : # Instructions exécutées à la création d'une instance
•def __eq__(self, val) : # redifinition de obj == val
•def __ge__(self, val) : redefinition de obj >= val
•...
en mettant les instructions de notre choix dans le bloc de la nouvelle définition.
Ce sont deux librairies pratiquement indispensables.
numpy contient les fonctions usuelles (sinus,....). Il se substitue au module math qu'il ne faut pas utiliser en même temps que numpy (parait-il).
matplotlib.pyplot permet de tracer des graphiques.
Comme leur nom est plutôt long à écrire il est pratique d'utiliser les alias suivants :
>>> import numpy as np
>>> import matplotlib.pyplot as plt
numpy procure un comportment voisin de Matlab.
>>> np.array([5,1,3,2])
array([5, 1, 3, 2])
>>> np.zeros(5)
array([0., 0., 0., 0., 0.])
>>> np.ones(5)
array([1., 1., 1., 1., 1.])
ATTENTION : zeros et ones générent des nombres flottants qui ne peuvent pas être utilisés comme indice. Si on veut des entiers, il faut ajouter un argument supplémentaire dtype (data type de numpy) qui permet de spécifier le type, par exemple int comme ceci :
>>>np.ones(5,dt ype=int)
array([1, 1, 1, 1, 1])
dtype reconnait les types prédéfinis suivants : int, bool, float, complex, bytes, str, ...Le nombre de bits (32, 64...) peut être précisé avec certains.
>>> np.random.random(4)
array([0.84498404, 0.62538097, 0.8748382 , 0.47472356])
>>> np.linspace(3, 4, num=5)
array([3. , 3.25, 3.5 , 3.75, 4. ])
>>> np.arange(3, 4, 0.2)
array([3. , 3.2, 3.4, 3.6, 3.8])
>>> np.sum(np.arange(1,10,1))
45
>>> np.min(np.array([5,2,7,4]))
2
>>> X=np.linspace(1,2,num=5)
>>> for y in X:
print(y)
1.0
1.25
1.5
1.75
2.0
>>> for i in range(len(X)):
print(i, X[i])
0 1.0
1 1.25
2 1.5
3 1.75
4 2.0
Les arrays de même dimension acceptent les opérations + - * / et **.
Les fonctions de numpy acceptent des listes (array)
>>> X=range(4)
>>> np.sqrt(X)
array([0. , 1. , 1.41421356, 1.73205081])
Tableaux multidimensionnels = tableau de tableau :
A = np.array([[1, 2, 3], [4, 5, 6]])
print(A)
[[1 2 3]
[4 5 6]]
B=A.flatten() # convertit en vecteur
print(B)
[1 2 3 4 5 6]
Mais aussi :
print(A.ravel())
[1 2 3 4 5 6]
print(A.ravel('C'))
[1 2 3 4 5 6] # convention langage C
print(A.ravel('F'))
[1 4 2 5 3 6] # convention langage Fortran
C=B.reshape(3, 2) # convertit en matrice 3x2
print(C)
[[1 2]
[3 4]
[5 6]]
Définition de grille meshgrid
Vx = [-0.5, 0, 0.5, 1, 1.5]
Vy = [-1, 0, 1, 2]
X,Y = np.meshgrid(Vx, Vy)
print("Matrice des abscisses")
print(X)
print("Matrice des ordonnées")
print(Y)
def f(x,y):
return x**2 + y**2
Z = f(X,Y)
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.view_init(40, -30)
ax.plot_surface(X, Y, Z)
plt.show()
Résultat :
Matrice des abscisses
[[-0.5 0. 0.5 1. 1.5]
[-0.5 0. 0.5 1. 1.5]
[-0.5 0. 0.5 1. 1.5]
[-0.5 0. 0.5 1. 1.5]]
Matrice des ordonnées
[[-1 -1 -1 -1 -1]
[ 0 0 0 0 0]
[ 1 1 1 1 1]
[ 2 2 2 2 2]]
La matrice des abscisses reproduit la ligne Vx len(Vy) fois
La matrice des ordonnées reproduit la colonne Vy len(Vx) fois
ce quit fait que X et Y ont même dimension et tous les len(Vx) x len(Vy) couples possibles sont inventoriés en prenant un x dans X et un y dans Y, ce que fait la fonction f(x,y)
import numpy as np
import matplotlib.pyplot as plt
def f(x):
return np.exp(-x**2)
a,b = -3,3
X = np.linspace(a,b,num=100)
# Plot et show
Y = f(X)
plt.plot(X,Y)
plt.show()
Pour mettre plusieurs plots sur le même graphe, les enchainer avant le plt.show().
#savefig
X = np.array([0,1,2,3,4,5])
Y = np.array([0,1,4,1,3,2])
plt.plot(X,Y-1) # ligne brisée
plt.plot(X,Y+1,linewidth=3,color='red') # paramètres divers
plt.scatter(X,Y) # nuage de points
plt.savefig("nomfich") # savefig à mettre avant plt.show()
plt.show()
# title, axis, grid, xlim
def f(x):
return np.exp(-x)*np.cos(2*np.pi*x)
a,b = 0,5
X = np.linspace(a,b,num=100)
Y = f(X)
plt.title('Amorti') # titre
plt.axis('equal') # repère orthonormé
plt.grid() # grille
plt.xlim(a,b) # bornes de l'axe des x
plt.plot(X,Y)
plt.savefig('amorti.png')
plt.show()
# label, legend
def f(x,k):
return 1/(1+np.exp(-k*x))
a,b = -5,5
X = np.linspace(a,b,num=100)
for k in range(1,5):
Y = f(X,k)
plt.plot(X,Y, label="k={}".format(k))
plt.legend() # Produit l'affichage des labels dans un cartouche
plt.show()
# plot 3D
Vx = [-0.5, 0, 0.5, 1, 1.5]
Vy = [-1, 0, 1, 2]
X,Y = np.meshgrid(Vx, Vy)
def f(x,y):
return x**2 + y**2
Z = f(X,Y)
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.view_init(40, -30)
ax.plot_surface(X, Y, Z)
# ax.plot_wireframe(X, Y, Z)
# plt.contour(X, Y, Z)
# plt.contour(X, Y, Z, 8) # 8 lignes de niveaux
plt.show()
Doc française récente ici : http://pascal.ortiz.free.fr/contents/tkinter/tkinter/index.html et très complète en anglais ici : https://tkdocs.com/shipman/
Pour faire du graphique facilement avec python : from tkinter import *
Il faut créer un objet fenêtre de nom quelconque (win par exemple), comme ci-après.
win = Tk()
win.title('Titre de la fenêtre') # Mettre un titre à la fenêtre
win.mainloop() # Démarrer la boucle de gestion des événements (dernière instruction en général).
win.resizable(False,False) # Pour empêcher le redimensionnement
Extraits de https://python.doctor/page-tkinter-interface-graphique-python-tutoriel
Après avoir déclaré une fenêtre, par exemple comme ceci :
fenetre = Tk()
on la remplit de widgets éventuellement regroupés dans cadres.
Exemple : Hello Worl :
# coding: utf-8
from tkinter import *
fenetre = Tk()
label = Label(fenetre, text="Hello World")
label.pack()
fenetre.mainloop()
Certains fichiers affichent des valeurs variables (int, float, string) que l'utilisateur peut modifier. Pour que cette modification soit immédiatement répercutée sur des variables du programme Tkinter offre pour cela des variables spéciales de type crées par les méthodes (de Tkinter) suivantes :
IntVar(), DoubleVar(), StringVar().
on peut créer les objets graphiques habituels de la manière suivante :
LABEL
label = Label(fenetre, text="Hello World", bg="yellow").pack()
BOUTON (Button)
btn=Button(fenetre, text="Fermer", command=fenetre.quit).pack()
btn.flash() : Provoque quelques clignotement du bouton. Après cela, il revient dans son état initial.
btn.invoke() : Appelle la fonction de rappel (callback) associée à l’option command et retourne ce que cette fonction retourne. N’a pas d’effet si le bouton est désactivé ou si aucune fonction de rappel ne lui est associé.
INPUT (Entry)
value = StringVar()
value.set("texte par défaut")
entree = Entry(fenetre, textvariable=value, width=30).pack()
Et l'accès au résultat se fera par un value.get()
StringVar est une classe qui étend la classe string et qui offre des mécanismes de synchronisation avce les widgets de Tkinter. Quand on modifie un StringVar le widget à qui on l'a attribué est automatiquement mis à jour.
CASE A COCHER ( Checkbutton)
chb = Checkbutton(fenetre, text="Nouveau?")
chb.pack()
deselect():Décoche la case à cocher.
flash():Fait clignoter la case à cocher quelques fois (entre les couleurs des états 'active' et 'normal'). Elle retrouve son état initial après le clignotement.
invoke():Utilisez cette méthode si vous souhaitez réaliser la même action que celle qui consiste à cliquer sur la case pour changer son état.
select():Coche la case à cocher.
toggle():Coche ou décoche la case à cocher selon son état courant.
BOUTONS RADIO ( Radiobutton)
value = StringVar()
bouton1 = Radiobutton(fenetre, text="Oui", variable=value, value=1)
bouton2 = Radiobutton(fenetre, text="Non", variable=value, value=2)
bouton3 = Radiobutton(fenetre, text="Peu être", variable=value, value=3)
bouton1.pack()
bouton2.pack()
bouton3.pack()
LISTBOX
liste = Listbox(fenetre)
liste.insert(1, "Python")
liste.insert(2, "PHP")
liste.insert(3, "jQuery")
liste.insert(4, "CSS")
liste.insert(5, "Javascript")
liste.pack()
CURSEURaLIRE (Scale)
value = DoubleVar()
scale = Scale(fenetre, variable=value)
scale.pack()
L'instruction pack() demande au widget de se dimensionner à sa taille minimale adéquate à son contenu et ensuite elle le rend visible.
Remarque : Le premier argument est le conteneur. Nous avons mis fenetre, mais cela aurait pu être cadre.
Frame
Les frames (cadres) sont des conteneurs qui permettent de regrouper des éléments.
fenetre['bg']='white'
# frame 1
Frame1 = Frame(fenetre, borderwidth=2, relief=GROOVE)
Frame1.pack(side=LEFT, padx=30, pady=30)
# frame 2
Frame2 = Frame(fenetre, borderwidth=2, relief=GROOVE)
Frame2.pack(side=LEFT, padx=10, pady=10)
# frame 3 dans frame 2
Frame3 = Frame(Frame2, bg="white", borderwidth=2, relief=GROOVE)
Frame3.pack(side=RIGHT, padx=5, pady=5)
# Ajout de labels
Label(Frame1, text="Frame 1").pack(padx=10, pady=10)
Label(Frame2, text="Frame 2").pack(padx=10, pady=10)
Label(Frame3, text="Frame 3",bg="white").pack(padx=10, pady=10)
PanedWindow
Le panedwindow est un conteneur qui peut contenir autant de widgets ou panneaux que nécessaire disposé horizontalement ou verticalement.
p = PanedWindow(fenetre, orient=HORIZONTAL)
p.pack(side=TOP, expand=Y, fill=BOTH, pady=2, padx=2)
p.add(Label(p, text='Volet 1', background='blue', anchor=CENTER))
p.add(Label(p, text='Volet 2', background='white', anchor=CENTER) )
p.add(Label(p, text='Volet 3', background='red', anchor=CENTER) )
p.pack()
SpinBox
La spinbox propose à l'utilisateur de choisir un nombre
s = Spinbox(fenetre, from_=0, to=10)
s.pack()
LabelFrame
Le labelframe est un conteneur avec un label.
l = LabelFrame(fenetre, text="Titre de la frame", padx=20, pady=20)
l.pack(fill="both", expand="yes")
Label(l, text="A l'intérieure de la frame").pack()
MESSAGEBOX
Nécessite d'importer tkinter.messagebox
from tkinter.messagebox import *
from tkinter import *
def callback():
if askyesno('Titre 1', 'Êtes-vous sûr de vouloir faire ça?'):
showwarning('Titre 2', 'Tant pis...')
else:
showinfo('Titre 3', 'Vous avez peur!')
showerror("Titre 4", "Aha")
fenetre = Tk()
Button(text='Action', command=callback).pack()
fenetre.mainloop()
TEXT
zone de texte :
Elle est crée part t = Tkinter.Text(parent, height = 10,....) La hauteur est exprimée en lignes de textes.
On insere du texte à la position coord par t.insert(coord , "blal\nbla"). coord est un string de la forme :
coord = "ligne.colonne" ou ligne est le numéro de la ligne de 1 au max et colonne est le numéro de la colonne de 0 au max :
•"1.0" est le tout début de la zone
•"10.end" est la position finale de la 10ème ligne
•tk.INSERT === "insert" est la position du curseur
•tk.CURRENT === "current" est la position la plus proche du curseur de la souris
•tk.END === "end" est la position après le dernier caractère
•tk.SEL_FIRST == "sel.first" est le début d'une sélection effectuée avec la souris
•tk..SEL_LAST == "sel.last" est la position après la sélection effectuée avec la souris
•... Voir la suite ici : tkinterReference_JW.Shipman_en.pdf
L'origine est toujours en haut à gauche, Y positif vers le bas.
Les tracés se font dans un canevas qui est créé dans la fenêtre comme suit :
canvas = Canvas(fenetre, ....)
Les arguments facultatifs les plus important sont :
width = valeur_Largeur,
height = valeur_Hauteur
Exemple :
canvas = Canvas(fenetre, width=150, height=120, background='yellow')
ligne1 = canvas.create_line(75, 0, 75, 120)
ligne2 = canvas.create_line(0, 60, 150, 60)
txt = canvas.create_text(75, 60, text="Cible", font="Arial 16 italic", fill="blue")
canvas.pack()
Fonctions de tracé dans le canevas :
create_arc() : arc de cercle (voir patate.py)
create_bitmap() : bitmap
create_image() : image
create_line() : ligne
create_oval() : ovale
create_polygon() : polygone
create_rectangle() : rectangle
create_text() : texte
create_window() : fenetre
Ecriture d'un texte incliné :
can.create_text(x,y,text="coucou", anchor="n", font="Arial 12",angle=ang)
Le texte est écrit dans un rectangle dont le coin Nord (anchor="n") a pour coordonnées (x,y). De plus le rectangle contenant le texte est pivoté de "ang" degrés dans le sens positif (pas documenté dans l'aide contextuelle).
Fonctions utiles sur les objets crées par create_xxx (il faut avoir mémorisé leur id) :
canvas.coords(id_élément, x0, y0, x1, y1) #Déplacement
canvas.delete(id_élément) #Effacement
canvas.focus_set() # Donne le focus pour interception du clavier
canvas.bind("<Key>", ma_callback) #interception du clavier
Les différents widgets ont en commun un grans nombre d'attibuts. Nous en listons quelques uns ici.
Nous avons déjà vu les attributs de dimension width= pour la largeur et height= pour la hauteur. Pour ces deux attributs on peut préciser l'unité par un caractère. Si absent l'unité est le pixel, sinon, il y a :
•c pour centimètre
•i pour inch (pouce)
•m pour millimètre
•p pour point d'impression(1/72 de pouce en général)
La position, toujours relative au coin haut gauche est précisée par les attributs x= et y=.
Les couleurs peuvent être précisées par un nom entre guillemets comme :
white (par défaut) ou red, 'blue, yellow, black, green, gray, light gray, dark gray, pink, orange, dark red, magenta, turquoise, gold...
On peut préciser la couleur en quantité de rouge/vert/bleu : Dans ce qui suit r représente un chiffre hexadécimal pour le rouge, v un chiffre hexadecimal pour le vert et b un chiffre hexadécimal pour le bleu
•#rvb cas de 4 bits par couleurs
•#rrvvbb cas de 8 bits par couleurs
•#rrrvvvbbb cas de 12 bits par couleurs
rar exemple, #fff est blanc, #000000 est noir, #000fff000 est un vert pur et #00ffff est un cyan pur (vert plus bleu).
La couleur du fond et précisée par background= ou bg=
On peut préciser les polices de plusieurs manières différentes dont :
Par une paire (famille, taille) ou triplet (famille, taille, forme) ou forme vaudra bold, italic, underline ou overstrike.
Par le nom qu'on lui a donné lors de sa création par la commande :
myFont = tkFont(option,…)
avec comme options :
•family= : 'Helvetica', 'Times', 'lucidatypewriter'
•size= : taille en points (si nombre >0) ou en pixels (si nombre < 0)
•weight= : 'bold' pour gras, 'normal' pour normal
•slant= : 'italic' pour italique, 'roman' pour un rendu normal
•underline= : 1 pour le soulignement, 0 pour un rendu normal.
•overstrike= : 1 pour barrer, 0 pour un rendu normal.
Pou avoir la liste des familles disponibles appeler la fonction tkFont.families().
Le Button est un des widgets qui a le plus d'attributs. Les plus importants sont marqués en rouge :
activebackground : Couleur de fond lorsque la souris survole le bouton.
activeforeground : Couleur du texte lorsque la souris survole le bouton.
anchor : Précise la position du texte dans le bouton (nw n ne w center e sw s se, center par défaut)
borderwidth ou bd : largeur de la bordure du bouton (2 par défaut)
background ou bg : Couleur de fond.
bitmap : Nom de l’un des bitmaps standards à afficher sur le bouton à la place du du texte.
command : Fonction ou méthode a appeler lorsqu’on clique sur le bouton.
cursor : Pour indiquer le pointeur de la souris à afficher lorsqu’on survole le bouton.
default : utiliser 'disabled' si le bouton doit être désactivé (grisé et ne répondant pas au clic de la souris), 'normal' est la valeur par défaut;
disabledforeground : Couleur du texte lorsque le bouton est désactivé.
foreground ou fg : Couleur du texte.
font : Police de caractère a utiliser pour le texte sur le bouton.
height : Hauteur du bouton en nombre de point si le bouton possède un texte ou en pixel pour les images.
highlightbackground : Couleur de la ligne qui indique que le bouton n’a pas le focus.
highlightcolor : Couleur de ligne qui indique que le bouton a le focus.
highlightthickness : Épaisseur de la ligne de focus.
image : Image a afficher sur le bouton à la place du texte.
justify : 'left', 'center' ou 'right' pour indiquer la position du texte.
overrelief : Le style de relief à utiliser lorsque la souris est sur le bouton, ('raised' par défaut)
padx : Marge additionnelle à gauche et à droite du texte
pady : Marge additionnelle en haut et bas du texte.
relief : Précise le type de relief appliqué au bouton.
repeatdelay : Voir l’argument suivant.
repeatinterval : Normalement, un bouton est déclenché une seule fois lorsque l’utilisateur relâche le bouton de la souris. si vous souhaitez que le bouton soit déclenché à des intervalles réguliers lorsque l’utilisateur maintient le bouton de la souris enfoncé, positionner cette option a un certain nombre de millisecondes à attendre entre chaque répétition et donner une valeur à l’option repeatdelay (ms) pour indiquer un délai après lequel le bouton est déclenché. Par exemple, si repeatdelay=500 et repeatinterval=100, le bouton sera déclenché après une demi-seconde puis redéclenché tous les dixièmes de secondes juqu’à ce que l’utilisateur relâche le bouton de la souris. Si l’utilisateur relache le bouton avant la durée repeatdelay, le bouton se déclenche normalement.
state – Positionner cette option à 'disabled' pour griser le bouton et le rendre inactif. Sa valeur est ‘active’ lorsque la souris est sur le bouton et 'normal' autrement.
takefocus : Normalement, en utilisant la touche Tab, on peut donner le focus aux bouton, et l’appui sur la barre espace a le même effet qu’un clic sur le bouton. Vous pouvez mettre takefocus a zéro pour empêcher cela.
text : Le texte a afficher sur le bouton.
textvariable : Une instance d’un StringVar() qui sera associée au texte du bouton. Si la variable est modifiée, un nouveau texte est affiché sur le bouton.
underline : valeur indiquant qu’aucun caractère du texte du bouton n’est souligné. Si sa valeur est positive ou nulle, le caractère correspondant du texte est souligné. Par exemple, underline=1 indique que le deuxième caractère du texte sera souligné (-1 par défaut).
width : Largeur du bouton en nombre de lettres (si du texte est affiché) ou en pixels (pour une image).
wraplength : Si on indique une valeur positive, le texte est affiché avec autant de lignes qu’il faut pour tenir dans la largeur fixé par wraplength.
La fonction de création d'un widget a pour premier argument le parent qui va le contenir. Ce peut être la fenêtre principale ou un widget de type contenaeur comme un Frame, un FrameLabel... Un Label, Entry, ... ne sont pas des conteneurs. Si un widget déclare un Label comme parent, il va se supposer à lui puisqu'il va se mettre à l'intérieur.
Pour gérer l'emplacement des widgets à l'intérieur d'un conteneur, il y a trois gestionnaires de placement qui font appel aux méthodes pack ou grid ou place des widgets internes. A priori, les widgets internes à un conteneur doivent tous utiliser la même méthode : ou pack() ou grid().
https://www.pythontutorial.net/tkinter/tkinter-pack/
Le gestionnaite pack utilise la méthode pack() de disposition la plus simple, utile pour des dispositions simples.
Les attributs permettent de gérer l'espace occupé par un widget à l'intérieur de son conteneur, où il faut distinguer l'espace qui lui est alloué de l'espace qu'il remplit effectivement, le restant restant vide.
La méthode pack() peut utiliser les attributs suivants :
side = "top" | "bottom" | "right" | "left" : indique le coté où il prend la place qui reste après ceux qui ont déjà pris ce même side. Un widget s'appuie, dans l'espace restant après positionnement des widget placés avant lui, sur le coté désigné par side.
Dans le sens perpendiculaire à side, toute la place de son conteneur est allouée au widget : si side = "top" ou "bottom", toute la largeur est allouée au widget. Si side = ""left" "ou right" toute la hauteur est allouée au widget.
expand = true, false : Si "true" l'espace restant dans le sens de side est alloué au widget, si "false", seul l'espace nécessaire à son contenu lui est alloué. Si plusieurs widget ont l'attribut à "true", il y a un partage d'allocation de l'espace restant.
fill = "x", "y", "both", "none" : Si "none" le widget n'occupera que l'espace qui lui est nécessaire dans l'espace qui lui est alloué. Si "x", "y" ou "both" il va s'étendre sur toute cette dimension dans son espace alloué.
ipadx = 0 marge intérieure en x qui agrandit l'espace interne effectivement rempli par le widget
ipady = 0 marge intérieure en y qui l'agrandit l'espace interne effectivement rempli par le widget
padx = 0 marge extérieure en x qui agrandit l'espace externe alloué au widget
pady = 0 marge extérieure en y qui agrandit l'espace externe alloué au widget
anchor = "center" "n", "s", "e", "w", "ne", "nw", "se", "sw" : Si le widget ne remplit pas tout l'espace qui lui est alloué, on le calera soit au centre, soit dans l"emplacement désigné les points cardinaux.
pack_forget() retire le widget de son emplacement, mais ne le détruit pas. Il peut être réutilisé).
ATTENTION :
https://www.pythontutorial.net/tkinter/tkinter-grid/
Le gestionnaire grid est également assez simple. il est imcompatible avec le gestionnaire pack pour le conteneur à l'intérieur duquel il gère le placement. Le placement d'un widget se fait dans la cellule ligne li, colonne co de la grille par la fonction grid(row=li, column=co,..).
Les cellules d'une même ligne ont toutes la même hauteur. Les cellules d'une même colonne ont toutes la même largeur. Un widget peut occuper plusieurs cellules adjacentes.
La taille de la grille correspond automatiquement aux plus grands numéros de ligne et de colonne utilisés (+1, car ils commencent à 0)
Les attributs suivants permettent de gérer la dsiposition :
row = : ligne de départ de position du widget (0 par défaut)
column =: colonne de départ de position du widget (0, par défaut)
rowspan =: nombre de lignes ocupées par le widget (1 par défaut)
columspan =: nombre de colonnes occupées par le widget (1 par défaut)
sticky =: coté vers lequel placer le widget NE N NW W SW S SE E (centre par défaut), s'il n'occupe pas toute la place de la cellule, W+E pour extension totale horizontale, N+S pour extension totale verticale et W+E+N+S pour occuper toute la place (que les lettres, pas les +)
padx = 0 marge extérieure en x qui l'entoure
pady = 0 marge extérieure en y qui l'entoure
ipadx = 0 marge intérieure en x qui l'agrandit
ipady = 0 marge intérieure en y qui l'agrandit
grid_forget() ou grid_destroy() retire le widget de la cellule (qui devient vide), mais ne le détruit pas. Il peut être réutilisé.
https://www.pythontutorial.net/tkinter/tkinter-place/
Le gestionnaire place permet de spécifier l'emplacement exact d'un widget en utilisant des coordonnées et dimensions absolues ou relatives pour l'espace alloué et anchor pour le position à l'intérieur de l'espace alloué.
Emplacement :
widget.place(x=50, y=50)
widget.place(relx=0.5, rely=0.5, anchor="center")
Dimensions
widget.place(width=120, height=60)
widget.place(relwidth=0.5, relheight=0.5)
L'instance fen de la classe Tk créée par fen = Tk() offre des méthodes de gestion des évènements et du temps, par exemple :
fen.after(5000, callback1)
appellera la fonction callback1 apres 5000 millisecondes.
La methode after existe également pour certains widgets (les canvas en particulier).
Si on veut tuer le timer avant qu'il arrive à échéance pour empêcher le lancement de l'action il faut récupérer son id = fen.after(5000, callback1) et le supprimer par la méthode after_cancel(id)
L'instruction suivante :
fen.bind("<Key>", callback2)
lie la fonction callback2 directement à la fenêtre (on peut la lier aussi à certains widgets).
callback2(e) sera appelée lors de l'appuie sur n'importe quelle touche du clavier. Le caractère entré s'obtient par e.char et son nom symbolique s'obtient par e.keysym.
A la place de <Key> on peut préciser un nom symbolique pour restreindre le champ des touches qui appellèreont la callback, comme :
<KeyPress> : lors de l'appui uniquement
<KeyRelease> : lors du lâcher uniquement
<Left>,<Right>,<Up>,<Down>
<space>, <Return>, <KP_Enter>, <Escape>
<Key_Release-a>, <Key_Release-A>, <KeyPress-a> == <a>, <KeyPress-A> == <A>
etc... De plus on peut combiner les symboles pour représenter des combinaisons de touche comme :
<Control-Shift-KeyPress-a>
On trouvera une liste des codes ici : http://tkinter.fdex.eu/doc/event.html#key-names
L'instruction suivante :
fen.bind("<Motion>", callback3)
lie la fonction callback3 directement à la fenêtre (on peut la lier aussi à certains widgets).
callback3(e) sera appelée chaque fois que la souris bougera. Sa position s'obtient par e.x et e.y.
Pour accéder à un explorateur de fichier Tkinter offre des modules que l'on accède via le module filedialog :
from tkinter import filedialog as fd
Ensuite on dispose des fonctions suivantes (qui toutes ouvrent un explorateur de fichier) :
•strname = askopenfilename(title='Open a file', initialdir='/', filetypes=filetypes)
•strnames = askopenfilenames(title='Open a file', initialdir='/', filetypes=filetypes)
•file = askopenfile(title='Open a file', initialdir='/', filetypes=filetypes)
•files = askopenfile(title='Open a file', initialdir='/', filetypes=filetypes)
Exemple acquisition d'un tuple des noms de fichiers
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog as fd
# La fenetre principale "root"
root = tk.Tk()
root.title('Display a Text File')
root.resizable(False, False)
root.geometry('550x250')
# Widget texte editable placé en mode grille en colonne 0, ligne 0
text = tk.Text(root, height=12)
text.grid(column=0, row=0, sticky='nsew')
# La callback associée au bouton d'accès à l'explorateur de fichier
def my_open():
filetypes = (('text files','*.txt'),('All files', '*.*'))
# Affichage boite de dialogue ouverture fichier
lesnoms = fd.askopenfilenames(filetypes=filetypes)
# Affichage des noms dans le widget text
for s in lesnoms:
text.insert('1.0', s+"\n")
# Le bouton de commande "Open" en mode grille en colonne 0 ligne 1
open_button = ttk.Button(root, text='Open a File', command=my_open)
open_button.grid(column=0, row=1, sticky='w', padx=10, pady=10)
# La mainloop()
root.mainloop()
Exemple ouverture directe d'un fichier :
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog as fd
# La fenetre principale "root"
root = tk.Tk()
root.title('Display a Text File')
root.resizable(False, False)
root.geometry('550x250')
# Widget texte editable placé en mode grille en colonne 0, ligne 0
text = tk.Text(root, height=12)
text.grid(column=0, row=0, sticky='nsew')
# La callback associée au bouton d'accès à l'explorateur de fichier
def my_open():
# file type
filetypes = (('text files', '*.txt'),('All files', '*.*'))
# Affichage boite de dialogue ouverture fichier
f = fd.askopenfile(filetypes=filetypes)
contenu = f.readlines() # Lecture du contenu
text.insert('1.0', contenu) # Affichage dans le widget text
# Le bouton de commande "Open" en mode grille en colonne 0 ligne 1
open_button = ttk.Button(root, text='Open a File', command=my_open)
open_button.grid(column=0, row=1, sticky='w', padx=10, pady=10)
# La mainloop()
root.mainloop()
Remarques :
f = fd.askopenfile() peut être remplacé par nom = fd.askopenfilename() suivi de
f = open(nom,"r");
Par défaut le contenue est interprété en ANSI. S'il est codé en utf-8, il faut ajouter dans open ou askopenfile l'argument encoding="utf-8" ou appliquer au string obtenir la méthode .decode('utf8')
Le package Pythonnet de Python permet de lier des bibliothèques .NET. Il s'installe depuis une console DOS avec pip :
pip install pythonnet
Les bibliothèques .NET sont nommées clr (Common Language Runtime). Pour pouvoir les utiliser, il faut les importer par l'instruction :
import clr
Exemple pour utiliser la méthode System.Console.Writeline de .NET dans Python :
import clr
# Ajouter une référence à une assembly .NET
clr.AddReference("System")
# Importer un namespace .NET
from System import Console
# Utiliser une classe .NET
Console.WriteLine("Hello, World!")
Exemple d'accès à une fonction .NET créée par un n'importe qui :
J'ai compilé avec Visual Studio en .Net Standard 2.0 la bibliothèque suivante :
namespace MyLibNetS2
{
public class Essai
{
public static double demi(double x) { return x / 2; }
}
}
Exemple d'accès à la dll obtenue depuis Python :
import clr
clr.AddReference(r'D:\MesProgs_Langages\python\ACCESS_DLL\MyLibNetS2.dll')
from MyLibNetS2 import Essai
print(Essai.demi(2))
Documentation :
http://opensimulator.org/git/opensim-libs-save/IronPython/IronPython-1.1.1/Tutorial/Tutorial.htm
IronPython est une mise en oeuvre open-source du langage de programmation Python qui est étroitement intégrée au cadre d'application .NET. L'IronPython peut utiliser les bibliothèques .NET Framework et Python, et d'autres langages de programmation .NET peuvent utiliser le code Python tout aussi facilement.
Le path d'accès à Iron Python :
Les scripts IronPython s'exécutent sous l'application ipy.exe qui doit être accessible dans le path. Pour mettre ipy.exe dans le path, en ce qui me concerne, faire :
•sous cmd.exe : path=C:\Program Files\IronPython 3.4;%PATH%
•sous powershell.exe : $env:PATH += ";C:\Program Files\IronPython 3.4\"
Dans Visual Studio Code, la console accessible sous l'éditeur fonctionne avec PowerShell. Pour lancer l'interpréteur IronPython, il faut soit faire :
$env:PATH += ";C:\Program Files\IronPython 3.4\"
pour ajouter ipy dans le path, soit créer un alias comme ceci :
Set-Alias ipy "C:\Program Files\IronPython 3.4\ipy.exe"
qui fonctionne directement :
ipy --version ==> IronPython 3.4.1
soit créer un raccourci :
$ipy = "C:\Program Files\IronPython 3.4\ipy.exe"
mais dans ce cas il faut appeler le lanceur de string & pour l'exécuter :
& $ipy --version ==> IronPython 3.4.1
La puissance d'IronPython réside dans sa capacité à accéder de manière transparente à la richesse des bibliothèques .NET.
L'importation des bibliothèques usuelles de .NET est immédiate sans passer par clr par contre il faut comme en Python classique faire un import des espaces de noms que l'on utilise.
import System est dans IronPython l''équivalent du #using System de c#.
Classe |
Propriété / Méthode |
Description |
System.DateTime |
Now |
Date et heure locales actuelles |
|
UtcNow |
Date et heure UTC actuelles |
|
Today |
Date actuelle à minuit |
|
AddDays(nb) |
Ajoute des jours |
|
ToString() |
Convertit en texte |
|
Year, Month, Day, Hour |
Accès aux composantes |
System.TimeSpan |
FromSeconds(sec) |
Crée une durée de sec secondes |
|
TotalSeconds |
Durée exprimée en secondes |
import System
print("Il est", System.DateTime.Now)
Classe |
Méthode |
Description |
System.Math |
Sin(x), Cos(x) |
Fonctions trigonométriques |
|
Sqrt(x) |
Racine carrée |
|
Pow(x, y) |
Puissance |
|
Round(x) |
Arrondi |
|
Abs(x) |
Valeur absolue |
|
PI |
La constante π |
import System
dir(System.Math) =====> Liste exhaustive
from System.Math import *
# permet d'accéder à toutes les méthodes c# de Math sans avoir à mettre de préfixe, à savoir :
Sin(PI/3) =====> 0.8660254037844386
Classe |
Méthode |
Description |
System.String |
Length |
Longueur |
|
Contains("x") |
Contient-il "x" ? |
|
Replace("a", "b") |
Remplace |
|
StartsWith("abc") |
Commence par… |
|
ToUpper(), ToLower() |
Majuscules / minuscules |
Mais,en pratique, on utilise plutôt les fonctions Python classiques que les chaînes .NET.
Classe |
Propriété / Méthode |
Description |
System.Console |
WriteLine("Hello") |
Affiche une ligne |
System.Environment |
MachineName |
Nom de la machine |
|
UserName |
Nom d’utilisateur |
|
NewLine |
Saut de ligne système |
|
TickCount |
Temps écoulé en ms depuis le démarrage |
Classe |
Méthode |
Description |
System.IO.File |
ReadAllText(path) |
Lit un fichier complet |
|
WriteAllText(path, texte) |
Écrit un texte dans un fichier |
System.IO.Directory |
GetFiles(path) |
Liste les fichiers |
|
Exists(path) |
Dossier existant ? |
System.IO.Path |
Combine(a, b) |
Construit un chemin correct |
from System.IO import File
texte = File.ReadAllText("C:\\Temp\\demo.txt")
print(texte)
Classe |
Méthode |
Description |
System.Random |
Next() |
Entier aléatoire |
|
NextDouble() |
Réel aléatoire dans [0,1) |
System.Guid |
NewGuid() |
Génère un GUID (UUID) |
import System
rng = System.Random()
print(rng.Next(100)) # entier aléatoire entre 0 et 99
Exemple avec la classe System.Collections :
from System.Collections import *
h = Hashtable()
h["a"] = "IronPython"
h["b"] = "Tutorial"
h["a"] ==> 'IronPython'
print(h["b"]) ==> Tutorial
for e in h: print(e.Key, ":", e.Value) ==>
...
b : Tutorial
a : IronPython
Pour instancier une classe générique (avec des éléments de divers types), le type des éléments doit être spécifié. IronPython utilise la syntaxe suivante pour spécifier les types des éléments : generic_type[type_élément, ...].
Exemple instance de liste générique de strings (type str) :
from System.Collections.Generic import *
L = List[str]()
L.Add("Hello")
L.Add("Bonjour")
for i in L: print(i) ==>
...
Hello
Bonjour
Pour utiliser des bibliothèques .NET supplémentaires, elles doivent être explicitement référencées et on utilise la même méthode qu'en Python classique avec Pythonnet.
>>>import clr
puis on utilise une des fonctions suivantes :
•>>>clr.AddReference("Malib.dll") fonctionnement aléatoire.
•>>>clr.AddReferenceToFileAndPath(...) pas testé,
•>>>clr.AddReferenceByName...) pas testé.
•>>>clr.AddReferenceToFile("MaLib.dll")
◦si la dll est dans le répertoire courant, il faut le mettre dans le path :
>>> import sys, os
>>>sys.path.insert(0,os.getcwd())
◦sinon, il faut mettre le chemin dans le path :
>>>sys.path.insert(0,"D:\tmp") dans le cas de D:\tmp\MaLib.dll
puis on importe les classes que l'on veut utiliser :
>>> from Malib import *
que l'on pourra utiliser comme dans c#.
Pour que la librairie c# Mapack soit acceptée par IronPython 3.4.1, j'ai dû la compiler en version .NET Standard 2.0 (la version 2.1 étant refusée).
Voici les principales dll .NET classiques généralement accédées via un clr.AddReference :
import clr
clr.AddReference ("System.Windows.Forms") # l’interface graphique
from System.Windows.Forms import Form, Button
clr.AddReference("System.Drawing") # les dessins
clr.AddReference("System.IO.Ports") # la communication
clr.AddReference("System.Configuration") # la configuration
Objet / Classe |
Description |
Form |
Fenêtre principale |
Button, Label |
Contrôles de base |
TextBox, ComboBox |
Saisie et sélection |
MessageBox.Show() |
Boîte de dialogue |
Timer |
Timer d’interface |
Objet / Classe |
Description |
Graphics, Pen |
Dessin vectoriel |
Color.Red, etc. |
Couleurs prédéfinies |
Font, FontStyle |
Police de caractères |
Point, Size, Rectangle |
Coordonnées et dimensions |
Bitmap, Image |
Manipulation d’images |
Objet / Classe |
Description |
Stopwatch |
Chronomètre haute précision |
Process |
Démarrer ou surveiller des processus |
Debug.WriteLine() |
Messages de débogage |
Installé par >pip install PyQt5
Voir https://www.gchagnon.fr/cours/python/pyqt.html#intro
bool
bytearray
bytes
classmethod
complex
dict
enumerate
filter
float
frozenset
int
list
map
memoryview
object
property
range
reversed
set
slice
staticmethod
str
super
tuple
type
zip
Voir : https://docs.python.org/3/library/functions.html
A
abs()
aiter()
all()
anext()
any()
ascii()
B
bin()
bool()
breakpoint()
bytearray()
bytes()
C
callable()
chr()
classmethod()
compile()
complex()
D
delattr()
dict()
dir()
divmod()
E
enumerate()
eval()
exec()
F
filter()
float()
format()
frozenset()
G
getattr()
globals()
H
hasattr()
hash()
help()
hex()
I
id()
input()
int()
isinstance()
issubclass()
iter()
L
len()
list()
locals()
M
map()
max()
memoryview()
min()
N
next()
O
object()
oct()
open()
ord()
P
pow()
print()
property()
R
range()
repr()
reversed()
round()
S
set()
setattr()
slice()
sorted()
staticmethod()
str()
sum()
super()
T
tuple()
type()
V
vars()
Z
zip()
_
__import__()
Voir : https://docs.python.org/fr/3/library/index.html
Services de Manipulation de Texte
string — Opérations usuelles sur des chaînes
re — Opérations à base d'expressions rationnelles
difflib — Utilitaires pour le calcul des deltas
textwrap --- Encapsulation et remplissage de texte
unicodedata — Base de données Unicode
stringprep — Préparation des chaines de caractères internet
readline — interface pour GNU readline
rlcompleter — Fonction de complétion pour GNU readline
Services autour des Données Binaires
struct — manipulation de données agrégées sous forme binaire comme une séquence d'octets
codecs — Registre des codecs et classes de base associées
Types de données
datetime — Types de base pour la date et l'heure
zoneinfo — Prise en charge des fuseaux horaires IANA
calendar — Fonctions calendaires générales
collections — Types de données de conteneurs
collections.abc --- Classes de base abstraites pour les conteneurs
heapq — File de priorité basée sur un tas
bisect — Algorithme de bissection de listes
array — Tableaux efficaces de valeurs numériques
weakref --- Weak references
types --- Dynamic type creation and names for built-in types
copy — Opérations de copie superficielle et récursive
pprint — L’affichage élégant de données
reprlib --- Alternate repr() implementation
enum — Énumérations
graphlib — Fonctionnalités pour travailler avec des structures de type graphe
Modules numériques et mathématiques
numbers — Classes de base abstraites numériques
Fonctions mathématiques — math
Fonctions mathématiques pour nombres complexes — cmath
decimal — Arithmétique décimale en virgule fixe et flottante
fractions — Nombres rationnels
random — Génère des nombres pseudo-aléatoires
statistics — Fonctions mathématiques pour les statistiques
Modules de programmation fonctionnelle
itertools — Fonctions créant des itérateurs pour boucler efficacement
functools — Fonctions d'ordre supérieur et opérations sur des objets appelables
operator — Opérateurs standards en tant que fonctions
Accès aux Fichiers et aux Dossiers
pathlib — Chemins de système de fichiers orientés objet
os.path — manipulation courante des chemins
fileinput — Parcourt les lignes provenant de plusieurs entrées
stat --- Interpreting stat() results
filecmp – Comparaisons de fichiers et de répertoires
tempfile — Génération de fichiers et répertoires temporaires
glob — Recherche de chemins de style Unix selon certains motifs
fnmatch — Filtrage par motif des noms de fichiers Unix
linecache — Accès direct aux lignes d'un texte
shutil --- Opérations de haut niveau sur les fichiers
Persistance des données
pickle — Sérialisation d'objets Python
copyreg — Enregistre les fonctions support de pickle
shelve — Persistance d’un objet Python
marshal — Sérialisation interne des objets Python
dbm --- Interfaces to Unix "databases"
sqlite3 — Interface DB-API 2.0 pour bases de données SQLite
Compression de donnée et archivage
zlib — Compression compatible avec gzip
gzip — Support pour les fichiers gzip
bz2 — Prise en charge de la compression bzip2
lzma — Compression via l'algorithme LZMA
zipfile — Travailler avec des archives ZIP
tarfile — Lecture et écriture de fichiers d'archives tar
Formats de fichiers
csv — Lecture et écriture de fichiers CSV
configparser — Lecture et écriture de fichiers de configuration
tomllib --- Parse TOML files
netrc — traitement de fichier netrc
plistlib --- Generate and parse Apple .plist files
Service de cryptographie
hashlib --- Algorithmes de hachage sécurisés et synthèse de messages
hmac — Authentification de messages par hachage en combinaison avec une clé secrète
secrets — Générer des nombres aléatoires de façon sécurisée pour la gestion des secrets
Services génériques du système d'exploitation
os — Diverses interfaces pour le système d'exploitation
io — Outils de base pour l'utilisation des flux
time — Accès au temps et conversions
argparse -- Analyseur d'arguments, d'options, et de sous-commandes de ligne de commande
getopt – Analyseur de style C pour les options de ligne de commande
logging — Fonctionnalités de journalisation pour Python
logging.config --- Logging configuration
logging.handlers — Gestionnaires de journalisation
Saisie de mot de passe portable
curses --- Terminal handling for character-cell displays
curses.textpad --- Text input widget for curses programs
curses.ascii --- Utilities for ASCII characters
curses.panel --- A panel stack extension for curses
platform — Accès aux données sous-jacentes de la plateforme
errno — Symboles du système errno standard
ctypes — Bibliothèque Python d'appels à des fonctions externes
Exécution concourante
threading — Parallélisme basé sur les fils d’exécution (threads)
multiprocessing — Parallélisme par processus
multiprocessing.shared_memory --- Shared memory for direct access across processes
The concurrent package
concurrent.futures --- Launching parallel tasks
subprocess — Gestion de sous-processus
sched --- Event scheduler
queue — File synchronisée
contextvars — Variables de contexte
_thread — API bas niveau de gestion de fils d'exécution
Réseau et communication entre processus
asyncio — Entrées/Sorties asynchrones
socket — Gestion réseau de bas niveau
ssl — Emballage TLS/SSL pour les objets connecteurs
select --- Waiting for I/O completion
selectors --- High-level I/O multiplexing
signal --- Set handlers for asynchronous events
mmap --- Memory-mapped file support
Traitement des données provenant d'Internet
email — Un paquet de gestion des e-mails et MIME
json — Encodage et décodage JSON
mailbox — Manipuler les boîtes de courriels dans différents formats
mimetypes --- Map filenames to MIME types
base64 — Encodages base16, base32, base64 et base85
binascii --- Conversion entre binaire et ASCII
quopri — Encode et décode des données MIME quoted-printable
Outils de traitement de balises structurées
html — Support du HyperText Markup Language
html.parser— Un analyseur syntaxique simple pour HTML et XHTML
html.entities — Définitions des entités HTML générales
Modules de traitement XML
xml.etree.ElementTree — L'API ElementTree XML
xml.dom — L'API Document Object Model
xml.dom.minidom --- Minimal DOM implementation
xml.dom.pulldom --- Support for building partial DOM trees
xml.sax — Prise en charge des analyseurs SAX2
xml.sax.handler --- Base classes for SAX handlers
xml.sax.saxutils — Utilitaires SAX
xml.sax.xmlreader --- Interface for XML parsers
xml.parsers.expat --- Fast XML parsing using Expat
Gestion des protocoles internet
webbrowser --- Convenient web-browser controller
wsgiref — Outils et implémentation de référence de WSGI
urllib — Modules de gestion des URLs
urllib.request --- Extensible library for opening URLs
urllib.response --- Response classes used by urllib
urllib.parse --- Parse URLs into components
urllib.error --- Classes d'exceptions levées par urllib.request
urllib.robotparser — Analyseur de fichiers robots.txt
http — modules HTTP
http.client — Client pour le protocole HTTP
ftplib — Le protocole client FTP
poplib --- POP3 protocol client
imaplib --- IMAP4 protocol client
smtplib --- SMTP protocol client
uuid — Objets UUID d'après la RFC 4122
socketserver — Cadriciel pour serveurs réseaux
http.server --- serveurs HTTP
http.cookies — gestion d'état pour HTTP
http.cookiejar --- Cookie handling for HTTP clients
xmlrpc --- XMLRPC server and client modules
xmlrpc.client --- XML-RPC client access
xmlrpc.server --- Basic XML-RPC servers
ipaddress — Bibliothèque de manipulation IPv4/IPv6
Services multimédia
wave --- Lecture et écriture des fichiers WAV
colorsys — Conversions entre les systèmes de couleurs
Internationalisation
gettext — Services d'internationalisation multilingue
locale — Services d'internationalisation
Cadriciels d'applications
turtle — Tortue graphique
cmd — Interpréteurs en ligne de commande.
shlex --- Simple lexical analysis
Interfaces Utilisateur Graphiques avec Tk
tkinter — Interface Python pour Tcl/Tk
tkinter.colorchooser — Boîte de dialogue de choix de couleur
tkinter.font — enveloppe pour les polices Tkinter
Boîtes de dialogue Tkinter
tkinter.messagebox – Invites de messages Tkinter
tkinter.scrolledtext — Gadget texte avec barre de défilement
tkinter.dnd – Prise en charge du glisser-déposer
tkinter.ttk — Widgets sur le thème Tk
tkinter.tix — Widgets d'extension pour Tk
IDLE