re

Introduction au langage Python3 - www.jchr.be

LE langage Python3 est un langage de programmation complet grâce aux nombreuses bibliothèques spécialisées. Utilisé dans l'industrie et dans la recherche, notamment par la NASA ou la recherche biomédicale, il est néanmoins idéal pour un apprentissage de la programmation, étant visuellement structuré.

Orienté objet, il est également utilisable comme un bon vieux BASIC, moyennant quelques différences par rapport à ce dernier :

Le langage Python a été créé par Guido van Rossum, qui s'en est déclaré le «bienveillant dictateur à vie». Il est distribué sous une licence Open Source depuis la version 2.1. Cela signifie que tout le monde peut l'utiliser librement, consulter le code-source et le modifier, redistribuer la version modifiée – sans obligation d'y joindre les sources – contrairement à la licence GPL où les sources modifiées doivent être disponibles pour toute nouvelle version distribuée.

Cette page fut commencée en mai 2002 comme manuel de références personnel. Elle prétend maintenant faciliter la prise en main du langage Python en GNU+Linux, d'autres UNIX, voire d'autres systèmes. Cette page est remaniée au fil des versions, mais rien ne garantit que les corrections sont complètes.

Les notes en beige concernent les spécificités de python2, dont le support s'est terminé au 31 décembre 2019. Cette page peut aider à adapter les anciens scripts.

Ces explications et informations peuvent vous aider – Vous êtes responsable de toutes utilisation qui pourraient endommager votre matériel ou vos données.

Pages liées à la présente

Pour mémoire, les spécificités de python2

Quelques modules internes: système et fichiers, mathématiques, chaînes, bases de données simple.

Modules externes : numpy (tableaux - math - random) - ECMA-48 (print at en couleur)

L'interface graphique du module TKinter

Quelques recettes et exemples

1. Prise en main

1.1 Installation

Sur un système Unix normalement configuré, on a l'obligation d'avoir les droits de super-utilisateur ("root") pour installer une application. Installez Python (par défaut, version 3.9.2 pour Debian 11.0 Buster - août 2021), et éventuellement son éditeur graphique idle-python3.9. En ligne de commande, on utilise par exemple sous Debian :

#En mode super-utilisateur: su [Enter] apt-get install python3 idle-python3.9

Sous SuSE, Mandrake et Fedora, vous devriez pouvoir utiliser une ligne de commande du type :

#En mode super-utilisateur: su [Enter] rpm -i python-3.7-19.6.i586.rpm

Une solution est également d'utiliser l'installateur graphique de ces distributions.

Il peut être intéressant, dans un script, de connaître la version de python pour faire agir le code en conséquence. Cela se fait par le module sys :

>>> import sys
>>> print(sys.version_info)
sys.version_info(major=3, minor=9, micro=2, releaselevel='final', serial=0)
>>> print(sys.version_info.major)
3
>>> print(sys.version_info.minor)
9
>>> print(sys.version_info.micro)
2
>>> print(sys.version_info.serial)
0
>>> print(sys.version_info[0])
3
>>> print(sys.version_info[1])
9
>>> print(sys.version_info[2])
2
>>> print(sys.version_info[4])
9

1.2 Le mode interactif

Ayant quitté le mode super-utilisateur (exit), python3 saisi dans une console affiche quelque chose qui ressemble à :

Python 3.7.3 (default, Apr  3 2019, 05:39:12)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Frappez 5 +3, puis [Enter] ou [Return] :

>>> 5 +3
8

En Unix, on quitte python en mode interactif avec quit() ou exit().

Pour python2, saisir tout simplement

python

Il existe un mode interactif amélioré nommé ipython3. Il offre notamment un historique des portions entières de code (boucles, fonctions…) qu'il est possible de corriger sans devoir reprendre les lignes une à une. On quitte ce shell avec quit() ou exit().

En python2, le logiciel s'appelle ipython.

1.3 Lancement d'un script de Python

À préciser

Un script est un fichier de programmation, rédigé avec un simple éditeur de texte. Supposons que le fichier script.py se trouve dans le répertoire /home/toto/python/ et contienne :

# commentaire : mon premier programme Python
print(5 +3)

Dans python interactif avec exec()

Il est possible de le lancer à partir d'une console où python3 a été lancé  :

>>> exec(open("/home/toto/script/essai.py").read())
8

Python2 avait pour ce faire execfile() :

>>> execfile("script.py")
8

Hors python interactif

Dans une console, frappez et saisissez :

$ python3 /home/toto/python/script.py

1.4 Lancement d'un script autoexécutable

Vous pouvez rendre le fichier /home/toto/python/script.py autoexécutable, à condition de savoir où se trouve l'application python. En UNIX, la commande whereis python renvoie (entre autres) une chaîne ressemblant à /usr/bin/python3, un script autoexécutable devra commencer (toute première ligne) par

#! /usr/bin/python3

Une version python2 s'appelle avec #! /usr/bin/python -Qnew (-Qnew pour la division «réelle» des entiers) :

#! /usr/bin/python -Qnew

Modifier ensuite les propriétés du script (il doit être exécutable au moins pour le propriétaire) par la commande (en tenant compte du chemin réel du script) :

chmod o +x /home/toto/python3/script.py

ou

chmod 740 /home/toto/python/script.py

ou par un gestionnaire de fichiers (le plus souvent par un clic droit sur le fichier). Il est dès lors possible de le lancer par la ligne de commande :

/home/toto/python/script.py

ou, si la console est positionnée dans le répertoire où se trouve le fichier :

cd repertoire-du-fichier
./script.py

Note : en UNIX, il n'est pas possible de lancer un exécutable (dont les scripts) situés dans une partition si la ligne correspondante dans /etc/fstab comprend noexec dans la colonne <options>.

1.5 Lancement par le navigateur

Ce genre d'appel ne permet pas de lire un message d'erreur lorsqu'une erreur interrompt le script. Lors de l'écriture, il vaut donc mieux lancer le script avec ./nom-du-script.py ou python3 nom-du-script.py dans une console.

Avec Gnome

Éditer le fichier suivant :

#! /bin/bash
gnome-terminal -e "python3 $1"
  1. gnome-terminal est l'application "console", elle pourrait être kterminal ou mate-terminal
  2. -e permet le lancement d'une application direstement dans la console
  3. python3 $1 lance python avec le script (représenté par $1)

Donner les droits d'exécution sur ce script (clic droit sur le fichier, Propriétés / Permissions)

Marquer les fichiers python :

  1. Clic droit sur un fichier terminant par .py
  2. Clic gauche sur Propriété / Ouvrir avec
  3. Clic gauche [+ Ajouter], puis Utiliser une commande personnalisée
  4. Introduire l'adresse du script ou le déterminer avec [Parcourir]

Attention à la priorité s'il y a plusieurs applications sélectionnées. La première s'appelle avec un double clic gauche ; une suivante avec le bouton droit de la souris, puis Ouvrir avec…

Avec KDE

  1. Dans konqueror, cliquer avec le bouton droit sur un fichier ayant l'extension .py
  2. Sélectionner dans le menu Édition / Modifier le type du fichier
  3. Cliquer sur Ajouter et sélectionner python parmi les "applications connues". Sinon, inscrire /usr/bin/python3 dans le champ éditable
  4. Veiller à ce que la case Lancer dans une console soit cochée
  5. Cliquer Appliquer.

Attention à la priorité s'il y a plusieurs application sélectionnées. La première s'appelle avec un double clic gauche ; une suivante avec le bouton droit de la souris, puis Ouvrir avec…

Une manière plus sophistiquée requiert de sauvegarder le script suivant, par exemple sous le nom py :

#! /bin/bash
konsole -e python3 $1
  1. Donnez-lui les droits d'exécution avec chmod 740 votrescript.py (ou modifiez ses propriétés avec konqueror)
  2. Sélectionnez un fichier se terminant par .py dans konqueror et choisissez Modifier le type de fichier (menu Édition)
  3. Cliquez sur le bouton Ajouter puis sur l'icone représentante un répertoire pour préciser l'endroit où vous avez sauvegardé le script py, puis Appliquer.

Pour une utilisation de la division «réelle», voir ci-dessus Avec Gnome

Notes :

Il se pourrait que la console appelée lorsque vous double-cliquez sur un fichier .py se referme le script terminé. Il faudra penser à terminer ces scripts Python par input() ou une de ses sophistications :

out =""
while out !="q":  # tant que le caractère n'est pas 'q'
  out =input("[q] + [Enter] pour quitter! ")

input() correspond à raw_input() en python2

1.6 Les éditeurs

idle-python3.7 (chiffres amenés à évoluer) est un éditeur écrit en Python qui devrait faciliter votre prise en main sous interface utilisateur. La première fenêtre est le mode interactif. On peut ouvrir une fenêtre de programmation, écrire et lancer un script à partir de cette fenêtre, après l'avoir sauvegardé. Pour Windows, c'est probablement une meilleure solution que blocnote qui ne proposant pas la coloration syntaxique, mais il en existe d'autres.

Sous idle, [F1] affiche une page d'aide, par exemple http://www.python.org/doc/current/.

Il existe aussi spe , Stani's python editor, qui installe 88Mo (non testé), et bien sûr vim et Emacs (qu'il faut bien connaître pour les utiliser).

Il est également possible d'utiliser les éditeurs des systèmes graphiques, comme gedit (Gnome), pluma (Mate-Desktop) ou kwrite (KDE), qui disposent de la coloration syntaxique pour la plupart des langages de programmation, plus facile à paramétrer sous kwrite que sous gedit, ce dernier ne proposant que cinq modèles peu engageants mais qu'il est possible d'aménager.

1.7 mode console sur smartphones 2015.08

Sur SailfishOS, python3 est nativement utilisable.

La programmation en python avec l'interface android nécessite le chargement d'un module, ce qui mériterait une page à part (qui n'existe pas sur ce site). Il est néanmoins possible de lancer un script dans une console sur android (bien que son interface soit peu pratique pour un long développement).

#qpy: console
print('bonjour le monde')

et appuyer sur la flèche "play" (triangle orienté à droite). Si le script s'est bien déroulé, il suffit d'appuyer sur le retour-chariot du clavier virtuel. S'il y a eu une erreur, cliquer et fermer la console «No.1» en haut à gauche. Pour permettre des caractères non ascii dans les chaînes ou les commentaires, utiliser la déclaration utf-8 :

# qpy: console
# -*- coding: utf-8 -*-
print('hélas le monde!')

1.8 La compilation

Il est possible de compiler un fichier-texte en un fichier-bytecode. Ce nouveau fichier ne sera pas directement exécutable par le système, mais sera interprété plus rapidement par l'application python3, qui devra donc toujours être installée. Il conservera sa compatibilité avec les autres plateformes, mais la compatibilité entre les différentes versions n'est pas garantie. Attention : le fichier .pyc généré par la compilation ne sera pas éditable : ne vous débarrassez pas de l'original .py.

Il y a plusieurs manières de compiler un fichier .py pour créer un fichier .pyc :

>>> python3 -c "import votreficher.py"

crée un répertoire __pycache__ contenant le fichier votreficher.cpython-3x.pyc (x selon la version de python3)

En mode interactif, en chargeant le module py_compile puis en lançant la compilation :

>>> import py_compile
>>> py_compile.compile("votrefichier.py")

Une manière plus rapide est d'importer le fichier python (cette façon lancera le fichier compilé !) :

>>> import votrefichier

Il est à noter que cette compilation n'accélère que l'interprétation du fichier, mais pas les fonctions internes de python. Un fichier Python constitué d'une seule fonction qui exécuterait un remplacement de caractères sur un fichier texte de 100Mo ne serait en rien accéléré par la compilation.

Dans une console, on lance ce fichier compilé avec python3 votrefichier.pyc

2. Structure

2.1 Syntaxe

Le langage Python a une syntaxe simple et lisible :

#! /usr/bin/python3

def factorielle(arg) :
  if arg ==0 :
    return 1
  return arg *factorielle(arg-1)

print(factorielle(43), factorielle(7))

Plutôt que les {} utilisées en C, PHP…, on utilise des indentations pour marquer la structure. La définition de la fonction factorielle() s'arrête au moment où le script se réaligne à la colonne 0. De la même manière, la condition imbriquée dans la fonction est également la cause d'une indentation (ici limitée à return 1). Les lignes vides sont facultatives et servent à mieux structurer le script.

# ce qui se trouve à droite d'un dièse est un commentaire (sauf dans une chaîne de caractères)
, sert à séparer des données qui se suivent (liste, dictionnaires, paramètres de fonctions…)
; sépare deux instructions se suivant sur la même ligne, inutile en fin de ligne
\ permet à une instruction de déborder sur la ligne suivante. Ce signe n'est pas nécessaire si '(', '[' ou '{' n'est refermé qu'à une ligne suivante.
: à la fin de la première ligne d'une condition, boucle ou fonction, annonce le bloc d'instructions alignées dans une même indentation.

A priori, les instructions se déroulent selon l'ordre dans lequel elles ont été écrites. Il peut être intéressant de ne permettre l'exécution d'une portion de code que sous condition, de la répéter dans des boucles ou d'écrire des séquences que l'on appellera à un endroit ou l'autre du programme : les fonctions, comme dans l'exemple vu plus haut.

2.2 Variables et assignations

Cette section est générale pour les différents types de variables : numériques, chaînes, tuples, listes, dictionnaires et ensembles.

Une variable contient une valeur ou plusieurs valeurs qui peu(ven)t être redéfinie(s) autant de fois que l'on veut, d'où le nom. Un ensemble de lettres minuscules ou majuscules, accentuée ou non, et même japonaises ou thaï, de chiffres et de tirets bas "_", mais ne commençant pas par un chiffre, peut représenter une variable :

En python2, un nom de variable (et de fonction) n'accepte classiquement que les minuscules ou majuscules latines non accentuées, le tiret bas et les chiffres à partir de la deuxième position.

Certains mots sont réservés à python et ne peuvent donc pas être utilisés comme nom de variable ou de fonction : and - as - assert - break - class - continue - def - del - elif - else - except - finally - for - from - global - if - import - is - lambda - not - or - pass - raise - return - try - while - with - yield

match et case sont réservés à partir de python 3.10

En python2, print et exec sont des mots réservés, remplacés en python3 par les fonctions print() et exec().

Avant python2.6, with et as ne sont pas des mots réservés, sauf à partir de python2.5 en cas de spécification from __future__ import with_statement en début de fichier (première ligne ne commençant pas par '#').

del Qio ou del(Qio) supprime la variable Qio, de quelque type que ce soit.

Le première utilisation d'une variable doit être une assignation, qui peut se faire de plusieurs manières : A =13, for i in [2,3,5] : ou def fonct(i =0, j, k) :

Attention ! Les variables ne sont pas nécessairement disponibles dans toutes les parties d'un script : voir fonctions.

Il est possible d'effectuer une permutations des valeur de variables, qui peuvent être de types différents (numériques, chaînes, listes…) :

>>> x =4 ; y ="trois" ; z =["a", "b"]
>>> x, y, z =y, z, x
>>> x, y, z
('trois', ['a', 'b'], 4)

type() permet de tester le type d'une variable. Par exemple, type([]) renvoie <class 'list'>. Attention : pour tester une variable, on ne peut utiliser la chaine "<class 'list'>", mais type([]) :

>>> li =["spam", "eggs"]
>>> type(li) ==type([])
True
>>> type(li) =="<type 'list'>"
False

En python2, type() renvoyait <type 'list'> et non <class 'list'>, ce qui ne change rien quand on utilise la bonne syntaxe ==type([])

Pour inscrire une variable parmi les variables du système, voir sys.intern().

En Python2, la fonction a =intern(chaîne) inscrit la variable parmi les variables du système, ce qui la rend plus rapidement mobilisable

Comme pour les listes, il est possible de construire un dictionnaire par une expression en compréhension :

li =range(1, 10)
dic ={i : i **5 for i in li}
print(dic)

Pour les dictionnaires propres à python, voir introspection.

2.3 Booléens et comparaison

Il existe deux valeurs booléennes (du mathématicien et logicien George Boole, 1815-1864) : True et False (Capitale + minuscules !).

Équivalents :

Attention : [[]], '0' et [0] sont True !

Les valeurs booléennes résultent souvent de l'évaluation d'une relation d'égalité, d'inégalité ou d'inclusion, qui sont souvent utilisées dans les structures conditionnelle (if et while).

>>> print(1 >2, 3 ==3, 1 in [0, 1, 2])
False True True

bool() retourne un True si l'argument est différent de 0, 0 +j0, "", None, [], {}, mais cette fonction ne semble pas très utile.

Comme les langages C et dérivés, Python fait une différence entre l'opérateur d'assignation a =2, qui attribue une valeur à une variable, et l'opérateur de comparaison a ==3, qui sert à tester l'égalité :

>>> a =2    # la valeur 2 est assignée à la variable a
>>> a ==3   # comparaison de la variable a (qui vaut deux) et la valeur 3
False

L'opérateur "est différent de" est noté !=

>>> a =2 ; a !=3
True

En python2, l'opérateur de test d'inégalité peut également se noter <>.

< plus petit que
<= plus petit ou égal à
> plus grand que
>= plus grand ou égal à

True et False valent respectivement 1 et 0 dans les opérations arithmétiques :

>>> a =3 ; print(a ==3) *5 +True
6

De ce fait, True peut valider une chaîne par multiplication ; False l'annihiler :

>>> nb =3 ; print(nb,"oeuf" +"s" *(nb>1), " et spam"*False)
3 oeufs

a is b est vrai si les valeurs ET les types sont égaux (voir variables numériques). De plus, id(a) équivaut à ce moment à id(b).

>>> a =123 ; b =123 +0j ; a ==b ; a is b
True
False

a is not b est vrai si les valeurs OU les types sont inégaux : int(1) is not float(1) est vrai

Les opérateurs de comparaison évaluent également les chaînes de caractères, <, <=, >, >= selon l'ordre alphabétique de leur code ASCII : ' ' < '0' < '1'… < 'A' < 'B'… < 'a' < 'b'… (voir caractères spéciaux). Les chaînes disposent en outre de

chaine1 in chaine2 est vrai si la première chaîne est contenue dans la seconde
chaine1 not in chaine2 est vrai si la première chaîne n'est pas contenue dans la seconde

Calcul booléen

Les expressions ci-dessus peuvent se composer :

expr1 or expr2 est vrai si l'une des deux est vraie (la seconde ne sera évaluée que si la première est fausse)
expr1 and expr2 est vrai si les deux sont vraies (la seconde ne sera évaluée que si la première est vraie)
not est la négation logique : not(1 ==2) est vrai

Attention : les expressions contenant or et and renvoient le dernier nombre évalué. Quand l'interpréteur rencontre l'expression 13 or 56, il se dispense d'évaluer 56, 13 étant différent de 0 et donc déjà vrai ; en rencontrant 13 and 56, l'interpréteur doit par contre évaluer le 56 puisque le premier terme vrai ne suffit pas : 3 and 5 vaut 5 car le second terme a dû être évalué, 5 and 3 vaut 3.

Pour les comparaisons bit à bit de deux nombres, utiliser &, |, ^ et ~ (voir Opérations sur les bits)

2.4 Conditions : if expr: … elif expr : … else : …

Une condition permet ou non le déroulement d'une portion de code. Un exemple sera plus éloquent qu'une explication a priori (notez l'indentation des parties de code à considérer ou non selon la condition) :

#! /usr/bin/python3
i =4 # on peut faire varier cette valeur
if i<5 :
  print(i, "est plus petit que 5")
elif i ==5 :
  print(i, "est exactement égal à 5")
else :
  print(i, "dans les autres cas, si i est plus grand que 5")
print("C'est fini")  #  ceci est hors condition, puisque sans indentation

if présente ce qui doit être fait si la condition qui le suit est rencontrée, elif permet de préciser une alternative soumise à condition ; else permet une alternative si aucune des conditions (if ou elif) n'a été rencontrée. elif et else ne sont pas obligatoires et l'un peut être utilisé sans l'autre.

#! /usr/bin/python3
a =-3
if a ==0 :
  print("=0")
elif a < 0 :
  print("< 0")
else :
  print("> 0")

Il est possible d'inclure une condition dans une autre :

#! /usr/bin/python3
i =7
if i<0 :
  if i%2 ==0 :
    print(i,"est négatif et pair")
  else :
    print(i,"est négatif et impair")
else :
  if i%2 ==0 :
    print(i,"est positif et pair")
  else :
    print(i,"est positif et impair")

Il est souvent possible de simplifier ces tests de parité :

if i %2 : # pour un i pair, la réponse est "0", valeur réputée fausse
  print("i est impair")
else :
  print("i est pair")

Parfois, la condition est bien cachée (a %2 est O et annule la chaîne im) :

a =1 ; print("%s est %spair" %(a, "im" *(a %2)))

Note : une condition peuvent être utilisées dans des définitions de listes en compréhension

2.5 Boucle while

La boucle teste une condition avant d'exécuter le bloc d'instruction indenté, et celui-ci sera répété tant que la condition sera vraie. Dans l'exemple suivant, la variable i sera incrémentée (augmentée) de 1 et imprimée jusqu'à ce qu'elle atteigne 10.

i =0
while i<11 :
  print(i)
  i +=1  # équivaut à  i =i +1

Note : while True :, while 1 : ou while not(0) : est toujours vrai et génère une boucle sans condition de sortie. On en sort généralement avec une condition amenant à break.

while True :
  a =input("[q] + [return] pour quitter: ")
  if a =='q' : break
  print("Réessayez")

else : introduit une séquence qui sera parcourue lors de la sortie normale de la boucle
break quitte immédiatement la boucle en évitant else
continue retourne directement au début de la boucle, ce qui permet d'éviter des tests de condition inutiles

nb =9
while nb !=0 :
  nb =input("0, 1, 2 ou 3? ")
  if nb ==1 : print("Choix un") ; continue
  if nb ==2 : print("Choix deux") ; continue
  if nb ==3 : print("Choix trois")

pass ne fait rien, mais est parfois nécessaire dans une syntaxe, par exemple pour forcer une indentation ou un réalignement.

2.6 Boucle for + iter()

for variable in collection permet de considérer l'un après l'autre chaque élément d'une collection :

for chaine in "bacon", 43, ["eggs","bacon"], {43:"eggs", "bacon":87} :
  print(type(chaine), chaine)

…la collection étant dans ce premier exemple un tuple (sans parenthèses dans ce cas-ci), tuple pouvant être lui-même être composite. La boucle classique du BASIC FOR I = x TO y utilise la liste produite par range :

for n in range(10) : # range(10) génére les valeurs de 0 à 9
  print(n, n *n)
  print("toujours dans la boucle puisqu'indentation")

n prend successivement toutes les valeurs de 0 à 9 (compris). Les instructions du bloc seront toutes activées 10 fois, et le programme continuera ensuite après le bloc défini sous la boucle for.

Il est possible de fixer un début, une fin et un pas, éventuellement négatif :

for var in range(10,4,-2) :
  print(var)

10
8
6

La succession de valeurs prises par la variable peut également provenir d'une chaîne :

for i in "Python" :
  print(i)

On peut imbriquer les boucles (notez les indentations successives) :

#! /usr/bin/python3
for i in range(1,11) :
  print("Table de multiplication par", i)
  for j in range(1,11) :
    print(i, "x", j, "=", i *j)
  print()  # ajoute de ligne entre chaque table
print("C'est tout")

Une boucle très simple peut s'écrire en une ligne, mais ne peut être précédée de quoi que ce soit : <<< a =1 <<< for i in range(1,5) : a *=i ; print(a)

Ceci ne fonctionnera pas : <<< a =1 ; for i in range(1,5) : a *=i ; print(a)

Instructions associées

continue retourne directement au début de la boucle, ce qui permet d'économiser les indentations :

chaine ="Le python est un langage élégant"
for i in chaine :
  if i !=" " :
    print(i)

devient

chaine ="Le python est un langage élégant"
for i in chaine :
  if i ==" " : continue
  print(i)

ce qui est appréciables dans les boucles longues et imbriquées.

else : introduit une séquence qui sera parcourue lors de la sortie normale de la boucle

break quitte immédiatement la boucle en évitant else

pass ne fait rien, mais est parfois nécessaire dans une syntaxe, par exemple pour forcer une indentation ou un réalignement. La boucle suivante pourrait servir à comparer (très) grossièrement la rapidité de deux systèmes :

#! /usr/bin/python3
import time
debut =time.time()
for i in range(1000) :
  for j in range(1000) :
    pass
print(time.time() -debut)

iter() permet la construction d'un objet itérable à partir d'une chaîne, liste, tuple ou dictionnaire, utilisable par la boucle for :

a =iter([1,2,3])
for i in a :
  print(i)

Il est possible d'utiliser iter qui appelle lui-même une fonction, à condition de donner une valeur-sentinelle qui stoppera la boucle lorsqu'une même valeur sera rencontrée. Dans le cas qui suit, la fonction hasard() retourne aléatoirement un nombre de 0 à 4 ; la boucle s'arrêtera au premier 3 fourni (qui ne sera pas imprimé).

#! /usr/bin/python3
import random
def hasard() :
  return random.randrange(5)
for i in iter(hasard, 3) :
  print(i)

2.7 match / case

À partir de python 3.10, sous réserves !

match présente la valeur à comparer, chaque cas étant introduit par case. Le cas «non rencontré» est symbolisé par le souligné _

q =input("Initiale d'une couleur primaire: ")
match q.lower() :
  case "m" :
    print("magenta")
  case "j" :
    print("jaune")
  case "c" :
    print("cyan")
  case _ :
    print("La réponse ne convient pas")

Peut remplacer if … elif … else moins lisible :

q =input("Initiale d'une couleur primaire: ").lower()
if q =="m" :
  print("magenta")
elif q =="j" :
  print("jaune")
elif q =="c" :
  print("cyan")
else :
  print("La réponse ne convient pas")

Cela ne fonctionne qu'avec une relation d'égalité, pas de sous-chaîne dans une chaîne, d'inégalité…

2.8 Structure with + as

with permet une opération locale. as (facultatif) permet de récupérer la valeur produite par l'opération qui suit with, par exemple le descripteur de fichier.

#! /usr/bin/python3

with open("essai.txt") as fd :
  print(fd.read())  # sortie console du fichier ouvert, uniquement dans la structure 'with'
print(fd.read())    # hors structure, génère 'ValueError: I/O operation on closed file'

On voit par cet exemple que le descripteur de fichier fd généré par l'ouverture du fichier n'est valable qu'au sein de la structure, python fermant proprement le fichier en fin de structure, même si le script est interrompu dans la boucle (pour les détails sur les fichiers, voir 6.3 Fichiers texte).

Note : il est possible de créer des objets utilisables dans cette structure à condition de les doter des méthodes __enter__() et __exit__()

Également à partir de python2.6 (et python2.5 avec l'instruction from __future__ import with_statement en début de script)

2.9 Traitement des erreurs

Plutôt que de subir une erreur, il est possible de tester une expression, de voir la réaction de l'interpréteur et de faire réagir le programme de façon adéquate avec except. else, facultatif, introduit une portion de code qui ne sera parcourue que s'il n'y a pas d'erreur.

#! /usr/bin/python3
try :
  1/0
except :
  print("Une erreur est apparue")
else :
  print("Tout va bien")
finally :
  print("Avec ou sans erreur")

Il est possible, et recommandé, de préciser une erreur particulière, ou plusieurs (dans, un, tuple) :

for i in range(-5, 6) :
  try :
    1 /i
  except ZeroDivisionError :
    print(" -")
  else :
    print("%.3f" %(1 /i))

Il est à noter qu'une simple condition suffit dans ce cas :

for i in range(-5, 6) :
  if i ==0 :
    print(" -")
  else :
    print("%.3f" %(1 /i))

Sans spécification de l'erreur attendue (voir listes des erreurs), except masque les autres erreurs possibles. C'est probablement pour cette raison que certains déconseillent la séquence try / except car elle peut rendre le débogage plus complexe.

finally (facultatif) introduit une portion de code qui sera parcourue dans tous les cas, erreur ou pas erreur.

raise KeyboardInterrupt produit l'exception précisée, par exemple pour une mise au point :

>>> raise KeyboardInterrupt, "Commmentaire facultatif"
Traceback (most recent call last) :
  File "<stdin>", line 1, in ?
KeyboardInterrupt: Commmentaire facultatif

assert produit l'exception particulière AssertionError en cas de test négatif, remplaçant la séquence if test : raise This_Error. On peut lui passer une valeur :

>>> assert 2 <1, "Comparison Error"
AssertionError: Comparison Error

Notes : Il est possible que des modules importés aient leurs propres exceptions, qui ne peuvent être listées ci-dessous.

2.A Liste des erreurs

Attention ! Une erreur difficile à localiser vient d'une ligne non terminée (il y manque par exemple une parenthèse fermante) : le système indique alors systématiquement la ligne suivante, où le code est pourtant correct.

Les types d'erreurs définis dans le module exceptions.py :

Et voici les avertissements :

3. Nombres

3.1 Types de variables numériques

Pour les généralités sur les variables, voir la section variables et assignations.

var =43 permet d'assigner une valeur à une variable numérique. En python3, les entiers n'omt pas de limite.

En python2, les entiers étaient définis de -2 147 483 648 à 2 147 483 647, et un L était nécessaire en fin de nombre pour que la variable soit reconnue comme «entier long».

nbr =2.65 est une variable «réelle» (en informatique, «réel» signifie "non entier")
nbr =265e-2 équivaut au précédent : 265 *10 **-2 =265 /100

Les «réels» ont une mantisse de 16 ou 17 chiffres, l'exposant va de -308 à 308 (cela dépend également du nombre de chiffres utilisés pour la mantisse). Pour fixer le nombre de chiffres pour la mantisse, voir le module decimal.

c =3 +4.1j est un nombre complexe (j ou J postposé qualifie la valeur imaginaire)
c.real renvoie la partie «réelle» du complexe
c.imag renvoie la partie imaginaire du complexe
c.conjugate() renvoie le nombre conplexe conjugué (a +bj et a -bj sont des complexes conjugués)

Python calcule dans l'ensemble des complexes (ici, la racine complexe d'un complexe) :

>>> (1 +4j) **(1 /(2 +3j))
(1.6758516946016602-0.20706889169199882j)

Types et conversions

print(type(var)) renvoie <type 'int'>, <type 'long'>, <type 'float'> ou <type 'complex'> selon la variable. Attention : les <type '*'> ne sont pas des chaînes :

>>> var =43 ; type(var) =="<type 'int'>"
False

Pour s'assurer qu'une expression est entière, on peut la comparer à un nombre qu'on sait être un entier :

>>> var =43 ; type(var) ==type(0)
True

Il existe un type de nombre permettant d'autres valeurs (l'infini…), voyez le module Decimal

int() transforme un nombre ou une chaîne conforme en entier illimité. Les «réels» sont arrondis par défaut

Avant la version python2.4, les entiers étaient limités de -2 147 483 648 à +2 147 483 647. Pour permettre une variable représentant un entier illimité, il fallait préalablement utiliser long(), le nombre produit étant terminés par un L. Depuis la version 2.4, il n'y a plus de problèmes lorsqu'un entier dépasse les limites : si un résultat se situe en dehors de cet intervalle, 'L' suit automatiquement le nombre : var =100000 *100000 équivaut à 10000000000L. Le L est supprimé en python3, tous les entiers étant illimités.

float() transforme un nombre ou une chaîne conforme en «réel»
complex() transforme des nombres, des variables ou une chaîne conforme (pas d'espace) en nombre complexe

>>> x =3.7 ; y =4.1 ; z =complex(x, y)

En python2, a, b =coerce(a, b) ajuste les variables numériques dans le type le plus englobant, avec la hiérarchie complexe > float > long > int

>>> a =3 ; b =2 **.5 ; a, b =coerce(a, b) ; print(a, b)
(3.0, 1.4142135623730951)

python3 ne connaît plus cette fonction.

3.2 Opérateurs numériques

= assigne une valeur à une variable : A =5, b =A
== test d'égalité entre variable(s) et valeur, qui retourne True ou False
+ additionne nombres et variables numériques
- soustrait une valeur à une autre ou à une variable
* multiplie deux nombres ou variables numériques
// permet la division entière, valable pour des «réels» :

>>> 7.7 //4
1.0

/ une division donne une réponse «réelle» :

>>> 7 /4
1.75

…même quand elle tombe «juste» :

>>> 32 /8
4.0

Veillez donc à utiliser // quand vous désirez que la réponse soit un entier.

En python2, la division de deux entiers était entière : 7 /4 retourne 1. Un point après un nombre force Python à considérer la réponse comme décimale :

>>> 7. /4
1.75

Il est possible en python2 d'utiliser / comme diviseur non entier en mentionnant en début de programme (future est entouré de part et d'autre de deux "soulignés") :

>>> from __future__ import division
>>> 7 /4
1.75

Ce n'est pas nécessaire si on lance python2.6 et suivants avec un paramètre :

$ python -Qnew

** marque l'exposant et a la priorité sur +, -, *, / (Attention : ^ est l'opération «et» sur les bits)
pow(x,y) renvoie x à la puissance y, équivaut à x **y
pow(x,y,z) renvoie x à la puissance y, puis le tout %z

Ces opérateurs s'organisent entre eux comme on a appris à l'école :

>>> (7 -3) *(3 +2) **2 donne 4 *5 **2 (=100)

Dans les formes x +=y, x -=y, x/=y, x//=y, x *=y, x **=y, x%=y… le premier opérande reçoit le résultat de l'opération :

>>> x =3 ; x +=2 ; x
5

round(x) arrondit un «réel», par excès (vers l'entier supérieur) à partir de .5 si la partie entière est impaire, et par défaut (vers l'entier inférieur) si la partie entière est paire. Cela permet d'éviter un biais lors d'un lot d'approximations.

>>> round(2.5)
2
>>> round(3.5)
4

En python2, round(x.5) est systématiquement arrondi par excès.

round(x,n) arrondit un «réel» à la décimale n (précision à la 15e décimale). n négatif permet un arrondi à la dizaine, centaine, au millier… près.

>>> round(3.14159,2)
3.14

jusqu'à python2.6, round() ne limite pas le nombre de chiffres après la virgule (voir print()) :

>>> round(3.14159,2)
3.1400000000000001

x %y ("x modulo y") renvoie le reste d'une division : 7%3 donne 1. Le résultat est toujours positif ou nul : -3 %7 renvoie 4
divmod() division renvoie une paire de nombres, le résultat entier et le reste :

>>> divmod(3,.7)
(4.0, 0.20000000000000018)

divmod(x,y)[0] équivaut à x //y
divmod(x,y)[1] équivaut à x %y
Une manière simple est d'utiliser un tuple pour recevoir les réponses :

resultat, reste =divmod(x,y)

max(x,y) renvoie la plus grande des deux valeurs
min(x,y) renvoie la plus petite des deux valeurs

max() et min() peuvent opérer sur les collections

abs() renvoie la valeur absolue d'un nombre (sans le signe)
abs(a +bj) renvoie le module du vecteur exprimé en coordonnées cartésiennes (l'hypothénuse du triangle rectangle dont les deux autres côtés sont a et b).

cmp() est supprimé

cmp(x, y), qui renvoie -1 si x <y , +1 si x >y et 0 si x ==y, est supprimée en python3. Elle est facile à écrire soi-même, voir la discussion et recette sur cette page.

Voir également le module math pour les fonctions mathématiques plus avancées sur les nombre, dont la fonction copysign(a,b) qui renvoie la valeur de a munie du signe de b.

3.3 Bases numériques

Même si l'on utilise généralement la base décimale (même sans le savoir), il en existe d'autres, où chaque rang vers la gauche représente une multiplication par une autre valeur que 10. Cela ne concerne qu'une manière d'encoder un même nombre.

Octal

L'octal (qui ne fonctionne qu'avec des entiers) est une base numérique où les chiffres ont des valeurs possibles de 0 à 7. Un nombre sous forme de chaîne octale commence par 0o : 0o253 vaut 2 *8 *8 +5 *8 +3 (= 171). oct() transforme un entier en chaîne octale :

>>> oct(43)
'0o53'

Pour transformer une chaîne octale en entier, il faut utiliser int("", 8) :

>>> int('0o53', 8)
43

Par défaut, une valeur est exprimé en décimal :

>>> print(0o53)
43

Notes : le formatage "%o" %(n) permet une transformation en chaîne :

>>> print("%d s'écrit %o en octal" %(43, 43))
43 s'écrit 53 en octal

En python2, une chaîne octale commence par 0 (zéro), mais python2.6 et 2.7 acceptent la notation 0o43.

En python2, 06.5 vaut le réel 6.5 en base 10

Hexadécimal

L'hexadécimal (qui ne concerne que les entiers) est une base numérique où les chiffres ont des valeurs possibles de 0 à 15, codées avec les chiffres de 0 à 9 et les lettres de a à f (valeurs 10… 15). Les nombres sous forme de chaîne hexadécimale commence par 0x ou 0X . 0x2b vaut 2 *16 +11 (=43)

hex(entier) retourne un nombre en chaîne hexadécimale :

>>> hex(43)
'0x2b'

Pour transformer une chaîne hexadécimale en entier, il faut utiliser int("", 16) :

>>> int('0x2b', 16)
43

Binaire

bin() permet de transformer un nombre en chaîne binaire, qui commence avec le préfixe 0b… et ne comprenant que des 0 et des 1 : 43 =0b101011

>>> bin(43)
'0b101011'
>>> print(0b101011)
43

Décimal

int(chaine) et long(chaine) convertissent une chaîne énoncée en base 10 en un nombre
int(chaine, base) permet de préciser une base, entre 2 et 36

>>> int("123456")
123456
>>> int("2b", 16) # le préfixe n'est pas nécessaire
43

La chaîne ne peut pas contenir de "chiffre" plus grand que ceux admis par la base. En base 36, les chiffres conventionnels et les 26 lettres de l'alphabet peuvent être utilisés, z ou Z représentant la valeur 35.

Rappel : en python2, long() permet d'assigner un nombre illimité «12345L».

3.4 Opérations sur les bits

var << n décalage des bits vers la gauche (équivaut à var *2 **n)
var >> n décalage des bits vers la droite (équivaut à var //2 **n)
Remarque : l'exposant a priorité sur la multiplication et la division.

var1 & var2 «et» logique : 1 si les deux bits correspondants valent 1

…001100 (12)
…000101 (5)
…000100 (4, résultat)

var1 | var2 «ou» inclusif : 1 si au moins 1 des deux bits correspondants vaut 1

…001100 (12)
…000101 (5)
…001101 (13, résultat)

var1 ^ var2 «ou» exclusif : 1 pour les bits correspondants différents

…001100 (12)
…000101 (5)
…001001 (9, résultat)

~var inversion de chaque bit d'une variable, ~nbr équivaut à -(nbr +1) : uniquement valable pour les entiers

…000010 (2)
…111101 (-3, résultat; ..1111 vaut -1, ..1110 vaut -2, ..1101 vaut -3)

Rappel ! (voir fin de Comparaisons et booléens)

4. Chaînes de caractères

Pour les généralités sur les variables, voir la section variables et assignations. Une chaîne de caractères peut également être considérée comme un tuple de caractères.

4.1 Affectation de chaînes

ch ="python" la variable ch reçoit la valeur "python"

ch ="C'est bien" une apostrophe peut être inclue dans une chaîne
V ='Un "faux"' les apostrophes permettent d'inclure des guillemets doubles
V ='C\'est "faux"' le caractère \ permet d'échapper («protéger») l'apostrophe dans une chaîne déterminée par des apostrophes
V ="C'est \"faux\"" le caractère \ permet d'échapper («protéger») les guillemets doubles dans une chaîne déterminée par des guillemets doubles
V ='123' la variable V reçoit une chaîne de trois chiffres

"""Trois doubles guillemets
permettent une chaîne
en plusieurs lignes"""   # sans commentaire à l'intérieur !

Le première utilisation d'une variable doit être une assignation, qui peut se faire de plusieurs manières : A ="", for i in "SPAM": ou def fonct(ch1 ="") :

len("python") renvoie la longueur d'une chaîne
type(expr) renvoie <type 'str'> si l'expression est une chaîne. Comparer avec la chaîne <type 'str'> ne fonctionne pas :

>>> type("chaine") =="<type 'str'>"
False
>>> type("chaine") ==type("")
True

chr(n) affiche un caractère à partir de son code numérique
ord("c") affiche le code numérique d'un caractère

Les caractères de 0 à 127 sont quasi-universels (ASCII =American Standard Code for Information Interchange) :

\x20   32   \x30 0 48   \x40 @ 64   \x50 P 80   \x60 ` 96    \x70 p 112
\x21 ! 33   \x31 1 49   \x41 A 65   \x51 Q 81   \x61 a 97    \x71 q 113
\x22 " 34   \x32 2 50   \x42 B 66   \x52 R 82   \x62 b 98    \x72 r 114
\x23 # 35   \x33 3 51   \x43 C 67   \x53 S 83   \x63 c 99    \x73 s 115
\x24 $ 36   \x34 4 52   \x44 D 68   \x54 T 84   \x64 d 100   \x74 t 116
\x25 % 37   \x35 5 53   \x45 E 69   \x55 U 85   \x65 e 101   \x75 u 117
\x26 & 38   \x36 6 54   \x46 F 70   \x56 V 86   \x66 f 102   \x76 v 118
\x27 ' 39   \x37 7 55   \x47 G 71   \x57 W 87   \x67 g 103   \x77 w 119
\x28 ( 40   \x38 8 56   \x48 H 72   \x58 X 88   \x68 h 104   \x78 x 120
\x29 ) 41   \x39 9 57   \x49 I 73   \x59 Y 89   \x69 i 105   \x79 y 121
\x2a * 42   \x3a : 58   \x4a J 74   \x5a Z 90   \x6a j 106   \x7a z 122
\x2b + 43   \x3b ; 59   \x4b K 75   \x5b [ 91   \x6b k 107   \x7b { 123
\x2c , 44   \x3c < 60   \x4c L 76   \x5c \ 92   \x6c l 108   \x7c | 124
\x2d - 45   \x3d = 61   \x4d M 77   \x5d ] 93   \x6d m 109   \x7d } 125
\x2e . 46   \x3e > 62   \x4e N 78   \x5e ^ 94   \x6e n 110   \x7e ~ 126
\x2f / 47   \x3f ? 63   \x4f O 79   \x5f _ 95   \x6f o 111   \x7f   127

le 127e caractère code en théorie delete, l'effacement du caractère suivant. Les caractères dont le code est inférieur à 32 sont des caractères de contrôle, dont certains ont des particularités intéressantes :

chr(0) code le caractère vide
chr(7) donne un bip
chr(8) revient d'un caractère à gauche, sans effacer le caractère présent
chr(9) saute à la tabulation suivante loin (colonnes octuples)
chr(10) en UNIX et MacOSX : retour chariot (première colonne, une ligne plus bas) ; DOS et MacOS9 : une ligne plus bas
chr(11) une ligne plus bas, sans changer de colonne
chr(12) une ligne plus bas, sans changer de colonne
chr(13) en UNIX, MacOSX et DOS : retour à la colonne 0, sans changer de ligne ; MacOS9 : retour-chariot
chr(27) introduit les codes d'échappement, voir ECMA

…dont certains peuvent être codés plus simplement dans une chaîne de caractères de Python :

\0 pour un caractère vide (contrairement au langage C, il ne s'agit pas d'une fin de chaîne)
\a émet un bip (comme chr(7))
\b pour revenir en arrière d'un caractère
\t pour une tabulation
\n pour un retour-chariot (tous systèmes)
\r pour revenir en début de ligne sans passer à la ligne suivante
\v pour passer à la ligne suivante sans revenir en début de ligne
\\ permet de coder le caractère \

repr(objet) représentation d'un objet sous la forme de chaîne avec les échappements pour qu'on puisse l'afficher avec print

>>> a ="C'est déjà ça"
>>> a ; print(a)
"C'est déjà ça"
C'est déjà ça
>>> repr(a) ; print(repr(a))
'"C\'est déjà ça"'
"C'est déjà ça"

En python2, où les chaînes ne sont constitués que d'octets, cela donne :

>>> a ="C'est déjà ça"
>>> a ; print(a)
"C'est d\xe9j\xe0 \xe7a"
C'est déjà ça
>>> repr(a) ; print(repr(a))
'"C\'est d\\xe9j\\xe0 \\xe7a"'
"C'est d\xe9j\xe0 \xe7a"

r'chaine' permet le codage d'une chaîne littérale, où les codes d'échappement \ ne sont pas évalués. Comparez :

>>> print("\43\n*")
#
*
>>> print(r"\43\n*")
\43\n*

4.2 Opérations sur les chaînes

Voir aussi le module 3.1 string

= assigne une valeur à une variable : chaine ='azerty'
+ prolonge une chaîne par une autre chaîne (concaténation) :

>>> ch1 ='ah ' ; ch2 ='bon!' ; ch1 +ch2
ah bon!

Il est possible d'effectuer une permutations des valeur de variables, qui peuvent être de types différents (numériques, chaînes, listes…) :

>>> x ='un', y ="deux", z ="trois"
>>> x, y, z =y, z, x
>>> x, y, z

* multiplie une chaîne par un entier

>>> _q ="ah" ; _q *3
ahahah

chaine[3] désigne le quatrième caractère de la chaîne

a ="chaîne"
for i in range(len(a)) :
  print(a[i])
c
h
a
î
n
e

En python2, les chaînes sont une suite d'octets et non de caractères. Or il faut par exemple deux octets pour coder le î.

a ="chaîne"
for i in range(len(a)) :
  print(a[i])
c
h
a
�
�
n
e

chaine =chaine[debut:fin] sélectionne une sous-chaîne à partir de la position debut (la première est 0) jusqu'à la position fin non comprise (la dernière est -1, l'avant-dernière -2…)
chaine[m:n:i] renvoie une chaîne composée du caractère m, puis tous les i caractères jusqu'au caractère n-1
chaine[0:] équivaut à la chaîne elle-même

"abaca".count("a") compte le nombre de "a" dans la chaîne
"abaca".count("a", 1) …à partir de l'élément à la position 1 (le "b")

str() converti un nombre en chaine :

>>> str(0.1)
'0.1'

repr() convertit également un nombre en chaine :

>>> repr(0.1)
'0.1'

li =chaine.split() découpe une chaîne (à chaque espace) et place les éléments dans une liste
li =chaine.split(cc) découpe une chaîne (à chaque sous-chaîne rencontrée) et place les éléments dans une liste
li =chaine.split(lim,n) découpe une chaîne un nombre limité de fois
li =chaine.rsplit(lim,n) découpe une chaîne un nombre limité de fois à droite

li =sorted(ch) retourne une liste triée des caractères utilisés dans la chaîne :

>>> sorted("Monty Python")
[' ', 'h', 'M', 'n', 'n', 'o', 'o', 'P', 't', 't', 'y', 'y']

chaine ="".join(liste) assemble dans une chaîne les éléments d'une liste de chaînes
chaine ="-".join(liste) assemble dans une chaîne les éléments d'une liste de chaînes séparés par des traits d'union (ou tout autre caractère ou toute autre chaîne)

filter(fonction, chaine) crée un filter object en utilisant une fonction, éventuellement créée pour l'occasion avec lambda

>>> list(filter(lambda x: 111 < ord(x) < 117, "python"))
['p', 't']

filter() peut souvent être remplacée par une condition dans une liste en compréhension :

>>> [x for x in range(10) if x%2 ==1]
[1, 3, 5, 7, 9]
>>> [x for x in "python" if 111 < ord(x) < 117]
['p', 't']

En python2, c'est une chaîne et non un filter object qui est retournée :

>>> filter(lambda x: 111>ord(x)>117, "python")
'pt'

li =sorted("azerty") produit une liste ordonnée des lettres composant une chaîne. Pour garder une chaîne, utiliser join() :

"".join(sorted("azerty")) ordonne les caractère de la chaîne : aertyz

ch ="abcdef" ; print(ch[::-1]) renverse la chaîne : fedcba
reversed("abcdef") produit un objet <reversed object> on peut l'égrener avec for i in reversed("abcdef") : ou le recomposer en chaîne avec "".join()
"".join(reversed("abcdef")) renverse également la chaîne (plus lent)

Attention : en python2/UTF-8, les caractères non ASCII (accentués et spéciaux) sont codés sur plusieurs caractères, traités un à un. Leur recombinaison ne permet généralement pas de coder valablement une chaîne :

>>> "chaîne"[::-1]
'en\xae\xc3ahc'
>>> print("chaîne"[::-1])
en��ahc

4.3 Comparaison de caractères et chaînes

max(chaine) renvoie le caractère dont le code numérique est le plus élevé
min(chaine) renvoie le caractère dont le code numérique est le moins élevé

max(ch1, ch2) renvoie la chaîne qui se classe alphabétiquement après l'autre
min(ch1, ch2) renvoie la chaîne qui se classe alphabétiquement avant l'autre

cmp(ch1, ch2) qui envoie 0 si les chaînes sont égales, -1 si la première se classe avant l'autre, 1 si la première se classe après l'autre, est supprimé en python3. Voir la recette pour une définition de la fonction cmp() .

x in y retourne True si la chaîne x est incluse d'un seul tenant dans y ; souvent utilisé dans une condition

Note : python considère logiquement que toute chaîne, même vide, contient la chaîne vide :

>>> "" in "spam" ; "" in ""
True
True

Tests Ajout 2016.02

Quelques tests renvoient un booléen True or False, unicode géré selon votre version de python (par défaut pour python3). Voir le sous-module curses.ascii, limité aux caractères ASCII (ord < 128).

print("é".isalpha()) # True
print("1".isdigit())
print("1".isalnum()) # réunit les deux précédents
print("e".islower())
print("A".isupper())
print(" ".isspace()) # True si ' ' (\x20), '\t' (\x09), '\n' (\x0a), '\v' (\x0b), '\f' (\x12), '\r' (\x0d), mais pas '\b' (\x08)

En python2, print("é".isalpha()) renvoie False

4.4 Formatage en chaînes Rév. 2014.12

Il est possible d'inclure des directives de formatage dans une chaîne, et faire suivre la chaîne d'un tuple %() contenant des valeurs ou des variables (nombre ou chaînes) :

>>> print("Imprimer le %s %d et %.1f, sa %s" %("nombre", 5, 2.5, 'moitié'))
Imprimer le nombre 5 et 2.5, sa moitié

%s pour une sortie générale (chaîne ou nombre)
%9s prévoit 9 caractères minimum pour la chaîne (éventuels espaces à gauche)
%-9s prévoit 9 caractères minimum pour la chaîne (éventuels espaces à droite)
%r entoure une chaîne de guillemets simples, un nombre sans
%c sort le caractère selon son code numérique : 65 =A, 66 =B, etc. (alternative à chr())

%d sortie entière (partie décimale tronquée, arrondissement «par défaut») de base décimale
%+d force l'affichage du + pour les nombres positifs
%4d pour un minimum de 4 caractères
%-4d pour un minimum de 4 caractères, espaces vides éventuels à droite
%04d remplace les vides éventuels par des 0
%i semble un parfait synonyme de %d dans toutes ses déclinaisons

Note : en Python 3.0 et 3.1, print("%,d" %(1234)) permettait d'afficher la virgule séparatrice de milliers, ce que fait format() (voir ci-dessous)

%o sortie octale (base 8) : 55 → 67 (6 *8 +7) (alternative à oct())
%x sortie hexadécimale (base 16 : 0…9, a, b, c, d, e, f) : 55 → 37 (3 *16 +5) (alternative à hex())
%X sortie hexadécimale où les lettres sont majuscules (base 16 : 0…9, A, B, C, D, E, F)

Note : en Python 3.0 et 3.1, %b permettait la sortie d'un entier en binaire, ce que fait format() (voir ci-dessous)

%f sortie décimale (virgule flottante) 5.5 → 5.500000 (6 chiffres après la virgule par défaut)
%9.3f sortie sur 9 caractères, dont un pour le point et 3 pour les décimales
%09.3f la partie entière nulle sera comblée de 0 : 4.3 → 00004.300
%.f arrondit à l'unité selon les règles académiques : 5.5 → 6  4.5 → 5 !

Pour supprimer l'éventuel zéro avant le point décimal, il faut supprimer le 0 initial avec [1:]

>>> print(("%.3f" %(5/6))[1:])
.833

%e pour une sortie scientifique : 55 → 5,500000e+01

%% permet d'afficher le caractère %

format()

format(valeur, "param") retourne une chaîne formatée pour une seule valeur. Le signe % n'est pas utilisé, et le paramétrage n'est pas tout à fait identique.

">9s" prévoit 9 caractères minimum pour la chaîne, un texte plus court se cale à droite, les espaces de remplissage à gauche
"<9s" prévoit 9 caractères minimum pour la chaîne, le texte se cale à gauche
"^9s" prévoit 9 caractères minimum pour la chaîne, texte centré

"9d" neuf caractères sont réservés pour le nombre, aligné à droite
"+9d" le signe est toujours présent, le signe positif n'est pas sous-entendu
"=+9d" le signe se met au début du nombre, le nombre est aligné à droite
"*=9d" le signe * est répété dans tous les espaces libres
"*=+9d" le signe est affiché, puis le caractère de remplissage *, puis le nombre
",d" affiche la virgule de séparation des milliers

"b" affiche un nombre sous sa forme binaire (0 et 1)
"o" affiche un nombre sous sa forme octale (0 à 7)
"x" affiche un nombre sous sa forme hexadécimale (0 à 9 et a à f)
"X" affiche un nombre sous sa forme hexadécimale (0 à 9 et A à F)
"#b" affiche le préfixe 0b devant le nombre binaire
"#o" affiche le préfixe 0o devant le nombre octal
"#x" affiche le préfixe 0x devant le nombre hexadécimal

"*=17+.3f" réserve 17 caractères pour l'expression d'un nombre «réel», dont 3 pour la partie décimale, le signe est mis en première place, le reste est rempli de *
"*=15+.3e" réserve 15 caractères pour l'expression scientifique d'un nombre «réel» :

>>> format(123456.789,"@=+15.3e")
'+@@@@@1.235e+05'

Il est possible de prévoir des champs à remplir à travers format() :

>>> "{1} et {0}".format('Romeo','Juliette')
'Juliette et Romeo'

Depuis python2.7, il est possible de remplir une chaîne lacunaire sans les numéros d'ordre :

>>> "{} et {}".format('Romeo', 'Juliette')
Romeo et Juliette

Il est possible d'énumérer une collection (ou d'épeler une chaîne) en la préfixant d'une astérique. Un surplus est ignoré, un manque déclenche l'erreur IndexError: tuple index out of range :

>>> "{} {}".format(*["Fahrenheit", 451])
'Fahrenheit 451'

Plus de spécifications sur format() ici

4.5 Encodage ISO-8859

Ce qui vous fera passer sans regret à python3 est l'usage par défaut du codage UTF-8, qui permet l'inclusion de tous les caractères dans les chaînes et les commentaires, et même de nombreux signes d'écritures non latines dans les noms de variables (ce qui n'est pas conseillé dans tous les cas).

En python2, l'encodage par défaut est l'ASCII, qui au sens strict ne code que les caractères de 0 à 127, ne permettant aucune lettre accentuée dans les chaînes et commentaires. En français, l'utilisation du standard ISO-8859-1 (latin-1) ou ISO-8859-15 (latin-9) est plus pratique mais il est nécessaire de le préciser (également possible en python3 bien que UTF-8 soit préférable) :

#! /usr/bin/python -Qnew
# -*- coding: latin-1 -*-
\xa0 160     \xb0 176 °   \xc0 192 À   \xd0 208 Ð   \xe0 224 à   \xf0 240 ð
\xa1 161 ¡   \xb1 177 ±   \xc1 193 Á   \xd1 209 Ñ   \xe1 225 á   \xf1 241 ñ
\xa2 162 ¢   \xb2 178 ²   \xc2 194 Â   \xd2 210 Ò   \xe2 226 â   \xf2 242 ò
\xa3 163 £   \xb3 179 ³   \xc3 195 Ã   \xd3 211 Ó   \xe3 227 ã   \xf3 243 ó
\xa4 164 ¤   \xb4 180 ´   \xc4 196 Ä   \xd4 212 Ô   \xe4 228 ä   \xf4 244 ô
\xa5 165 ¥   \xb5 181 µ   \xc5 197 Å   \xd5 213 Õ   \xe5 229 å   \xf5 245 õ
\xa6 166 ¦   \xb6 182 ¶   \xc6 198 Æ   \xd6 214 Ö   \xe6 230 æ   \xf6 246 ö
\xa7 167 §   \xb7 183 ·   \xc7 199 Ç   \xd7 215 ×   \xe7 231 ç   \xf7 247 ÷
\xa8 168 ¨   \xb8 184 ¸   \xc8 200 È   \xd8 216 Ø   \xe8 232 è   \xf8 248 ø
\xa9 169 ©   \xb9 185 ¹   \xc9 201 É   \xd9 217 ù   \xe9 233 é   \xf9 249 ù
\xaa 170 ª   \xba 186 º   \xca 202 Ê   \xda 218 Ú   \xea 234 ê   \xfa 250 ú
\xab 171 «   \xbb 187 »   \xcb 203 Ë   \xdb 219 Û   \xeb 235 ê   \xfb 251 û
\xac 172 ¬   \xbc 188 ¼   \xcc 204 Ì   \xdc 220 Ü   \xec 236 ì   \xfc 252 ü
\xad 173 -   \xbd 189 ¼   \xcd 205 Í   \xdd 221 Ý   \xed 237 í   \xfd 253 ý
\xae 174 ®   \xbe 190 ¾   \xce 206 Î   \xde 222 Þ   \xee 238 î   \xfe 254 þ
\xaf 175 ¯   \xbf 191 ¿   \xcf 207 Ï   \xdf 223 ß   \xef 239 ï   \xff 255 ÿ

l'octet 160 est l'espace insécable (&nbsp; en html) ; l'octet 173 la possibilité de césure (&shy; en html, dont la valeur ne semble pas universellement reconnue). Les quelques variantes de l'iso-8859-15/latin9 sont : \xa4 164 € – \xa6 166 Š – \xa8 168 š – \xb4180 Ž – \xb8 184 ž – \xbc 188 Œ – \xbd 189 œ – \xbe 190 Ÿ

Il est également possible d'utiliser l'encodage ci-dessus de la manière suivante :
\x + code hexadécimal ou chr(code décimal) : "ça" s'écrit "\xe7a" ou chr(231) +"a"

Pour disposer des(164), Š (166), š (168), Ž (180), ž (184), Œ (188), œ (189) et Ÿ (190) plutôt que ceux indiqués ci-dessus, spécifier iso-8859-15 ou latin-9.

latin-1 (iso8859) est de plus en plus remplacé par utf-8 (unicode) qui permet tous les caractères, les idéogrammes et même le cunéiforme (mais il faut que les caractères existent sur une fonte chargée sur votre système).

Notes :

4.6 Chaînes unicode

L'UTF-8 permet un codage du plus grand nombre de caractères typographiques possible, dont les dizaines de milliers d'idéogrammes chinois officiels, les hiéroglyphes ou les différents systèmes cunéiformes. Les caractères ASCII (lettres non accentuées et signes typographique usuels, dont le code est inférieur à 128) restent les mêmes, tous les autres étant codés sur deux, trois ou quatre octets supérieurs à 127 : lettres accentuées, caractères non latin ou signes typographiques moins usuels (π … —).

L'universalité a un prix : en latin-1 (iso8859-1), les 192 caractères sont codés par un seul octet, pour seulement 96 en UTF-8. Mais pour peu que vous utilisiez beaucoup de caractères non latins ou des caractères graphiques dans une page HTML, un texte en UTF-8 est plus léger que les "entités" telles &mdash; ou &#x3c0;

Forme d'encodage (pour a, b, c… valant 0 ou 1) :

Ces nombres sont théoriques : en dessous de 32, seuls les octets 9, 10, 13 sont définis : certaines plages ne sont pas (encore) utilisées, d'autres sont réservées. Par ailleurs, un système d'exploitation n'est capable d'afficher ces caractères que dans la mesure où des polices les contenant sont installées.

Le format UTF-8 est pratique pour les programmeurs : si un caractère est codé avec une suite de quatre octets WXYZ, aucun autre caractère n'est codé par les doublets WX, XY ou YZ ou les triplets WXY ou XYZ, ce qui signifie qu'une séquence de deux (ou trois) octets codant un caractère unicode ne peut être contenu dans une séquence codant un autre caractère. Cela permet des remplacements de séquences d'octets représentant des caractères unicode en étant sûr de ne pas en altérer d'autres.

Par contre, il y a en général plus d'octets que de caractères dans une chaîne unicode. Le codage UTF-8 d'un fichier-texte en français compte environ 5% d'octets de plus que de caractères.

Le module unicodedata permet d'obtenir des indications sur les caractères unicode :

>>> import unicodedata
>>> print(unicodedata.category(u"œ"), "---", unicodedata.name(u"œ"))
Ll --- LATIN SMALL LIGATURE OE

Utiliser l'unicode

En python3, le codage est par défaut en UTF-8. Il ne faut préciser un codage que s'il s'agit d'un autre : latin-1, iso8859-15… On utilise donc toutes les lettres accentuées ou non, latines ou non, pour les chaînes, les commentaires et même les noms de variable.

En python2, il faut déclarer l'UTF-8 pour utiliser l'unicode en commençant un script par :

#! /usr/bin/python -Qnew
# -*- coding: utf-8 -*-

L'éditeur de texte utilisé doit alors sauvegarder le script en utf-8, et la console utilisée en permettre l'affichage.

Chaînes unicode Rév. 2016.03

Pour donner un exemple plus évident qu'un idéogramme chinois, nous allons prendre le caractère é (qui existe dans le codage iso-8859-1/latin-1) au delà de l'octet 127. Dans une console python3, saisissez-le entouré de guillemets, en python3

>>> "é"
'é'

…et en python2 / UTF-8

>>> "é"
'\xc3\xa9'

qui nous montre que é est codé en deux octets en Python2 (chacun est représenté en hexadécimal). La longueur de la chaîne représentant é vaut 1 en python3 / UTF-8 , 1 en python2 / latin-1, et 2 en python1 / UTF-8 :

>>> len("é")
1
>>> len("é")
2

En console configurée en codage UTF-8, ces deux octets ne sont pas affichables séparément, puisqu'ils ne peuvent y exister qu'en séquence d'au moins deux octets :

>>> print("\xc3\xa9 \xc3 \xa9")
é � �

Python3 n'a pas le même comportement :

>>> print("\xc3\xa9 \xc3 \xa9")
é à ©

En python3, ord() renvoie le rang unicode du caractère :

>>> print(hex(ord("é")))
0xe9
>>> print("\xe9")
é

ascii() code une chaîne avec non-ASCII (avec des lettres accentuées) en chaîne comportant des octets et

>>> print(ascii("pµə"))
'p\xb5\u0259'

Note : les caractères entre 128 et 159 du cp1252 sont codés par leur équivalent unicode au delà de 255, voir cette page (1,2Mo).

Python2 dispose d'un objet unicode, et même si un caractère spécial est codé en plusieurs octets, la longueur de la chaîne unicode vaut 1 :

>>> u"œ" ; type(u"œ") ; len(u"œ")
u'\u0153'
<type 'unicode'>
1

Transformation (python2 uniquement !)

unicode("chaine","encodage") retourne un objet unicode utilisant l'encodage spécifié (la longueur de la première chaîne vaut 5, celle de la seconde chaîne est de 3) :

unicode("43€","latin-1")
u'43\xe2\x82\xac'
>>> unicode("43€","utf-8")
u'43\u20ac'

Cela permet de modifier le type de codage d'une chaîne.

>>> u"é" in unicode("pétunia","utf-8") :
True

unichr(entier) retourne un caractère unicode à partir d'un entier (ici en hexadécimal) :

>>> unichr(0x20ac)
€

L'utilisation de unicode() n'est pas neutre sur la longueur d'une chaîne. Dans une console configurée en utf-8, l'application python lancée :

>>> len(unicode("société","utf8"))
>>> 7
>>> len(unicode("société","latin"))
>>> 9

Dans une console configurée en iso8859-15/latin-9, l'application python lancée :

>>> len(unicode("société","latin-9"))
>>> 7
>>> len(unicode("société","utf8"))
Traceback (most recent call last) :
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf8' codec can't decode byte 0xe9 in position 4 : invalid continuation byte

Notes :

utf8 ou utf-8 sont équivalents
latin, latin1, latin-1, iso8859 et iso8859-1 sont équivalents
1252 permet une trentaine de caractères supplémentaires, voyez cette page.

python3

En python3.4, pour retrouver une chaîne d'octets à partir d'une chaîne unicode, utiliser encode (decode n'existe plus). 197 et 147 codent en deux octets le caractère unicode œ. Comparer :

>>> ch ='œuf'
>>> for i in ch :
…    print(i)
…
œ
u
f

et

>>> ch ='œuf'.encode("utf8", "strict")
>>> for i in ch :
…            print(i)
…
197
147
117
102

ch est alors de la classe bytes.

4.7 Objets bytes et bytearray Rév. 2022.11

Python3 codant par défaut les caractères en utilisant un à quatre octets… (UTF-8), la longueur d'une chaîne n'est plus le nombre d'octets qui la composent, et il n'est plus possible de coder les octets 225 ou 237 par un caractère comme avec les encodages latin-1 par exemple… Les tableaux d'octets sont des objets bytes, notamment utilisés pour lire et écrire les fichiers binaires.

Les octets entre \x32 et \x127 peuvent s'écrire avec les caractères ASCII correspondant, le reste est écrit en notation hexadécimale, soit deux chiffres hexadécimaux (de 1 à 9 et de a à f) préfixé par \x. Par exemple, 169 (16 *10 +9) se code \xa9 (a =10 ; b =11 ; c =12 ; d =13 ; e =14 ; f =15 ).

b'' définit un objet bytes en utilisant les caractères non accentués, ponctuation courante et opérateurs ou la notation hexadécimale à deux chiffres :

>>> b"w\x45\xff"
b"wE\xff"

…où \x45 est rendu avec son équivalent ASCII E (économie d'écriture).

Il est à noter que si un objet bytes ressemble à une chaîne, il s'agit en fait d'un tuple d'entiers ayant pour valeurs possibles de 0 à 255 :

>>> oc =b"ay\xff"
>>> oc[1] ; type(oc[1])
121
<class 'int'>

bytes() transforme une chaîne en objet bytes si l'on précise un encodage :

>>> bytes("là", encoding="utf-8") # trois octets en UTF-8
b'l\xc3\xa0'
>>> bytes("là", encoding="latin-1") # deux octets en latin-1
b'l\xe0'
>>> class(bytes("0"))
<class 'bytes'>

D'autres types de données peuvent servir à créer un objet bytes :

>>> bytes([245, 23, 56, 255]) # les listes simples d'entiers entre 0 et 255 compris
b'\xf5\x178\xff'
>>> bytes((33, 64, 255)) # les tuples d'entiers entre 0 et 255 compris
b'!@\xff'
>>> bytes({3:"456", 33:"et"}) # les clés (entières entre 0 et 255 compris) de dictionnaires (! vaut pour 33)
b'\x03!'

Un entier seul génère initialise un objet 'bytes' à autant d'octets nuls :

>>> bytes(7) #
b'\x00\x00\x00\x00\x00\x00\x00'

…ce qui peut servir à réserver un objet 'bytes' d'une certain nombres d'octets. Mais comme il n'est pas possible de modifier un élément d'un objet bytes, l'intérêt est peut-être limité.

Pour sauvegarder un tel objet, il faut utiliser un fichier binaire :

ch =bytes("déjà là", encoding="utf-8")
with open("fichier.bin","wb") as fd :
  fd.write(ch)

bytearray

Les objets bytes se comportent plus comme des tuples que comme des listes : il n'est pas possible de modifier un de ses éléments. Pour un objet dont on veut modifier les éléments, utiliser un objet bytearray :

>>> a =bytearray([0, 33, 53]) ; a
bytearray(b'\x00!5')
>>> a[2] =54 ; a
bytearray(b'\x00!6')

…variable qui pourra également être sauvegardée dans un fichier binaire. Il est possible d'initialiser un 'bytearray' de n octets vides avec bytearray(n).

En python2, bytes() et b"" encode selon l'encodage de la console ou du traitement de texte (toujours <type 'str'>) :

>>> bytes("déjà") # console en encodage unicode
'd\xc3\xa9j\xc3\xa0'
>>> bytes("déjà") # console en encodage latin-9 / ISO-8859-15
'd\xe9j\xe0'

5. Collections

Pour les généralités sur les variables, voir la section variables et assignations.

Python connaît plusieurs types de collections (tuples, listes, dictionnaires et ensembles…) c'est-à-dire de variables composées d'éléments qui peuvent être divers (nombres, chaînes ou parfois d'autres collections). Les chaînes sont considérées comme des tuples simples de caractères.

5.1 Tuples (,)Rev. 2019.12

Pour les généralités sur les variables, voir la section variables et assignations.

Un tuple (parfois traduit en français par n-uple) est une séquence peu modifiable, une collection ordonnée d'éléments qui peuvent être des chaînes, nombres, listes, tuples, ensembles…

tup =(1,2,"trois",[4,5],6) ou tup =1,2,"trois",[4,5],6 définit le tuple tup. 1 est au décalage 0, 2 est au décalage 1, "trois" au décalage 2, le sous-tuple (4,5) au décalage 3…
tup =(5,) ou tup =5, une virgule permet de n'assigner qu'un élément à un tuple : tup =(5) équivaut à tup =5, variable entière
tup =1,2,3,(4,5),6 les parenthèses d'un éventuel sous-tuple sont toujours nécessaires

tup[3][1] (notez les crochets !) renvoie 5, le second élément du sous-tuple à la position 4 (la numérotation des positions commence à 0)

tuple() transforme une liste, chaîne, ensemble ou rassemble les clés d'un dictionnaire en tuple
type(var) renvoie <type 'tuple'> si l'expression est un tuple

len(tup) renvoie le nombre d'éléments d'un tuple. len((1,(2,3),4)) ne contient que 3 éléments

Un tuple ne supporte pas une assignation de valeur à un de ses éléments ni sa suppression, les élément d'un tuple n'étant pas modifiables (utilisez des listes pour cette fonctionnalité) :

tup =3, 5, 6 ; tup[2] =45 renvoie TypeError: object doesn't support item assignment :
tup =3, 5, 6 ; del tup[1] renvoie TypeError: 'tuple' object does not support item deletion

Un tuple est donc figé et ne peut être modifié que par une rédéfinition ou par un ajout d'élément(s). Pour une variable tup :

>>> tup =("a","b")
>>> tup +=("c",)
>>> tup
('a', 'b', 'c')

tup =() définit un tuple vide, extensible avec +=

* permet de multiplier un tuple par un entier

>>> tup =(0, "", None, False)
>>> tup *3
(0, '', None, False, 0, '', None, False, 0, '', None, False)

*= assigne directement le résultat à la variable

tup =("a","b","c","d") ; tuple(reversed(tup)) renverse un tuple : ('d', 'c', 'b', 'a')
"".join(("a","b","cd","ef")) joint le tuple de caractères/chaînes en une chaine : "abcdef"

Python considère une chaîne comme un tuple de caractères :

>>> li =[1,"eggs"] ; print(li[1][3])
's'

Les chaînes étant considérés comme des tuples de caractères, il est possible de séparer les caractères par un (ou plusieurs) caractère(s) avec join()  :

>>> "-".join("abcd")
'a-b-c-d'

5.2 Listes [,]

Pour les généralités sur les variables, voir la section variables et assignations.

Une liste est une collection ordonnée, une séquence modifiable d'objets divers : nombres, chaînes, listes, tuples, dictionnaires, ensembles… Chaque élément est classé selon un index numérique et peut être librement redéfini (une chaîne peut être remplacée par un nombre ou une collection).

Les listes ne sont pas des tableaux, mais il est possible de les utiliser comme tels. Pour les véritables tableaux, voir le module externe numpy.

li =[2,"oh",9,47] définit la liste li, composée de 4 valeurs : le nombre 2 est au décalage 0, la chaîne "oh" est au décalage 1, 9 au décalage au 2, etc.
len([2,"oh",(6,3),9,47]) renvoie le nombre d'éléments de la liste, en l'occurrence 5 éléments, dont le tuple (6,3).

list() transforme en liste une chaîne, un tuple, un ensemble, ou rassemble les clés d'un dictionnaire

>>> list("spam")
['s', 'p', 'a', 'm']

li[0] désigne le premier élément de la liste, li[1] le deuxième…
li[-1] désigne le dernier élément de la liste, li[-2] l'avant-dernier…

li[1] =43 assigne la valeur 43 à la deuxième place de la liste li

li =[1,9,[7,4,5]] une liste peut en contenir une autre parmi ses éléments
li[2][0] désigne le premier élément de la sous-liste à la troisième position : 7

liste =liste[debut:fin] sélectionne une plage de liste à partir de la position debut(la toute première est 0) jusqu'à la position fin non comprise (la dernière est -1, l'avant-dernière -2…)

li[3:7] à partir de la quatrième position jusqu'à la huitième position non comprise
li[3:] à partir de la quatrième jusqu'à la dernière comprise
li[0:-1] exclut le dernier élément
li[:-2] à partir de la première position jusqu'à l'avant-dernière non comprise
li[m:n:i] renvoie l'élément au décalage m, puis tous les i éléments jusqu'à n-1

li[:0] =['a','b','c'] ajoute des éléments en début de liste
li[2:2] =['a','b','c'] insère des éléments entre les positions 1 et 2
li[m:n] =['a','b','c'] supprime les positions m à n-1 et insère des éléments entre les positions m et n
del li[m:n] supprime les positions de m à n-1,

slice(start, end, step) prépare un découpage selon les attributs start, stop et step, soit les trois arguments possibles (stop seul, start et stop, ou les trois ensemble, les attributs non définis renvoient none) :

>>> i =slice(1, 7, 2)
>>> print(i.start, i.stop, i.step)
1 7 2

Exemple d'utilisation :

i =slice(1, 7, 2)
print("python"[i])

li =[] initialise une liste vide, peut être nécessaire lorsqu'elle doit partir de rien, voir exemple
+ prolonge une liste par une autre liste

>>> li =["Spam"] ; li +[3]
["Spam", 3]
>>> li =li +3
TypeError: can only concatenate list (not "int") to list

Pour ajouter un ou des élément·s à une liste, il faut l(es) entourer de [] :

>>> li =[2, 3, 5, 7]
>>> li +=[11, 13] ; li
[2, 3, 5, 7, 11, 13]

Pour ajouter une sous-liste, il faut l'entourer deux fois : [[]] :

>>> li =[2, 3, 5, 7]
>>> li +=[[11, 13]] ; li
[2, 3, 5, 7, [11, 13]]

* permet de multiplier une liste

>>> ["Spam"] *3
['Spam','Spam','Spam']

+= et *= assigne directement le résultat au premier terme

Attention à l'assignation simple d'une liste à une autre, car cette assignation est en fait identité :

>>> liste =[1, 2, 3] ; autre =liste
>>> autre +=[7] ; print(liste, autre)
[1, 2, 3, 7] [1, 2, 3, 7]

autre n'est donc pas une autre liste comportant les mêmes éléments, mais un alias. On utilise list() ou b =a[:] pour copier entièrement une liste dans une autre :

>>> originale =[1, 2, 3] ; copie =list(originale)
>>> copie +=[7] ;
>>> print(originale, copie)
[1, 2, 3] [1, 2, 3, 7]

Attention ! Il n'est pas possible de créer un tableau de dimension deux de la sorte, chaque modification sur une des sous-listes se répercutant sur les autres  :

>>> echiquier =[[0] *8] *8
>>> echiquier[3][3] =7
>>> echiquier
[[0, 0, 0, 7, 0, 0, 0, 0], [0, 0, 0, 7, 0, 0, 0, 0], [0, 0, 0, 7, 0, 0, 0, 0], [0, 0, 0, 7, 0, 0, 0, 0],
[0, 0, 0, 7, 0, 0, 0, 0], [0, 0, 0, 7, 0, 0, 0, 0], [0, 0, 0, 7, 0, 0, 0, 0], [0, 0, 0, 7, 0, 0, 0, 0]]

Il existe une recette pour produire ce genre de tableaux.

Pour générer des listes, voir 5.7 Génération de collections

Liste et doublons

Pour enlever les doublons d'une liste, il est possible de passer par un ensemble, qui est une collection (non ordonnée) d'objets uniques

>>> print(list(set([1,1,3,4,5,5,5])))
[1,3,4,5]

Cela ne marche pas pour toutes les listes, comme par exemple celles qui contiennent des sous-listes ou d'autres types de collections : voir cette recette.

5.3 Méthodes pour les listes

li.count(x) compte le nombre d'occurrences de la valeur x dans la liste
li.count(x,n) …à partir de l'élément à la position n

li.index(x) retourne le décalage de la première occurrence de x dans la liste (ValueError si n'existe pas)
li.index(x,n) retourne le décalage de la nième occurrence de x dans la liste (ValueError si moins de n occurrences de x)
li.pop() renvoie le dernier élément et le supprime de la liste (IndexError si la liste est vide)
li.pop(i) retourne l'élément au décalage i, le supprime de la liste et ramène tous les élément suivants (IndexError si la liste est vide)
li.remove(x) supprime la première occurrence de la valeur x dans la liste. Provoque une erreur si la valeur x n'existe pas ! Solution :

if x in li :
  li.remove(x)

li.insert(i,valeur) insère une valeur au décalage i en repoussant les éléments suivants, ou en l'ajoutant à la fin si le décalage équivaut au nombre d'éléments de la liste
li.append() ajoute un élément (nombre, chaîne, liste, tuple, dictionnaire) à la fin d'une liste
li.extend(seq) étend une liste avec chaque élément d'une séquence : les caractères d'une chaîne, les élément d'une liste ou d'un tuple, ou chaque clé d'un dictionnaire. Pour li =[1,2,3,4] et ch ="abc" :

>>> li.append(ch)
[1, 2, 3, 4, 'abc']
>>> li.extend(ch)
[1, 2, 3, 4, 'a', 'b', 'c']

li =chaine.split() découpe une chaîne (à chaque espace) et place les éléments dans une liste
li =chaine.split(ch) découpe une chaîne (à chaque sous-chaîne) et place les éléments dans une liste
chaine =" ".join(liste) assemble dans une chaîne les éléments d'une liste de chaînes, avec l'espace (ou toute autre caractère défini) comme séparateur.

Trier une liste

li.sort() trie la liste exprimée sous forme de variable, sans devoir recevoir le résultat dans une variable
nv =sorted([8, 1, 3, 5, 4]) (depuis Python2.4) renvoie une liste triée ; la liste de départ n'est pas elle-même triée

li.reverse() inverse une liste exprimée sous forme de variable, sans devoir recevoir le résultat dans une variable
liste2 =li[::-1] copie une liste inversée

li.sort(reverse=True) combine les deux précédents

Pour rendre le tri insensible à la casse (pas de distinctions entre majuscules et minuscules), utiliser key=str.lower  :

>>>
['a', 'A', 'B', 'b']

Tri selon les valeurs d'une «colonne» en particulier

Les listes qui comportent des sous-listes («rangées») sont triées en tenant compte des premiers éléments des sous-listes (première «colonne»). En cas d'égalité, les seconds éléments sont évalués; etc.

li.sort(key =operator.itemgetter(n)) permet de définir la colonne (n) sur laquelle la liste doit être triée (importer préalablement le module operator).

>>> import operator
>>> li =[[1,4],[3,2]]
>>> li.sort(key=operator.itemgetter(1))
>>> li # le 2 de [3,2] passe avant le 4 de [1,4] : (1) pour les seconds éléments
[[3,2],[1,4]]
>>> li.sort(key=operator.itemgetter(O))
>>> li # le 1 de [1,4] passe avant le 3 de [3,2] : (0) pour les premiers éléments
[[1,4],[3,2]]

Attention :

5.4 Dictionnaires { : , }

Pour les généralités sur les variables, voir la section variables et assignations.
Python3 et python2.7 connaissent une nouvelle forme de dictionnaire : OrderedDict, qui conserve la mémoire de l'ordre d'entrée de ses éléments.

Un dictionnaire est une collection non ordonnée d'objets modifiables, accessibles par des clés. La clé d'un élément peut être un nombre (même «réel» ou complexe), une chaîne ou même un tuple (mais pas une liste ni un dictionnaire) :

>>> hindi ={1:"ek", 2:"do", 3:"tin", 4:"char"} ; hindi[1]
'ek'

La clé est une valeur (chaîne ou nombre, même complexe) ou une variable contenant une telle valeur.

>>> hindi ={1:"ek", 2:"do", 3:"tin", 4:"char", 5:'panch'}
>>> hindi[1]
'ek'

Attention : un dictionnaire n'est pas une liste : on accède à la valeur d'un dictionnaire par sa clé, non par son décalage :

>>> hindi ={'un': 'ek', 'deux': 'do', 'trois': 'tin', 'quatre': 'char', 'cinq': 'panch'}
>>> print(hindi["cinq"]) # la clé est ici la chaîne 'cinq'
>>> hindi[3]
KeyError: 3

Par contre, une valeur peut être une liste, à l'intérieur de laquelle un décalage peut servir :

>>> dic ={'spam': [1, 2, "eggs", 4]}
>>> dic['spam'][2] # affiche le décalage [2] de la liste dont la clé est 'spam'
"eggs"

Les valeurs d'un dictionnaire peuvent également être un dictionnaire :

adresses ={}
adresses["pim"] ={"rue":"5, rue de la Gare", "ville":"4321 Petaouchnok" }
adresses["pam"] ={"rue":"7, Grand-place", "ville":"1234 Trifouillis" }
adresses["poum"] ={"rue":"3, rue des arbres" }      # peut se faire en
adresses["poum"] ={"ville":"3412 Hout-Si-Plout" }   # plusieurs fois
print(adresses["poum"])
print(adresses["pam"]["ville"])

Note : cela ressemble beaucoup aux «objets» ("adresses"), «instances» ("pim", "pam", "poum") et «attributs» ("rue", "ville") de la programmation orientée objet.

dico ={} et dico =dict() initialisent un dictionnaire
type(dico) renvoie <type 'dict'>, mais comparer un dictionnaire avec la chaîne "<type 'dict'>" ne fonctionne pas, il faut utiliser type({}) ou type(dict())  :

>>> mondico ={4:"spam", 3:"egg"}
>>> type(mondico) ==type({})
True

del dico[cle] enlève le couple cle:valeur d'un dictionnaire
del dico[1:3] retourne TypeError: unhashable type : pas de référence par place

Attention : des variables peuvent représenter des valeurs pour les clés. Mais dans l'exemple suivant, même si a et b sont différents dans la forme id(a) !=id(b), ils sont égaux au point de ne pouvoir être les clés de deux valeurs différentes : la variable b remplace la valeur de la variable a utilisée comme clé ; appeler dic[b] équivaut à appeler dic[a] puisque leur valeur commune est 2.

>>> a =2 +0j ; b =2
>>> id(a) ==id(b)
False
>>> dic ={a:25, b:31}
>>> dic
{(2 +0j): 31}
>>> dic[a] ; dic[b]
31
31

Note : une liste peut contenir un ou plusieurs dictionnaire·s non nommé·s, accessible·s par leur position dans la liste :

>>> li =[{}, {}, {}]
>>> li[0]["a"] =3 ; li[0]["b"] =4 ; li[2]["c"] =5
>>> li
[{'a': 3, 'b': 4}, {}, {'c': 5}]

Attention : de la même manière que pour les listes, dic1 =dic2 n'assigne pas seulement les valeurs de dic2 à dic1, mais fait de dic1 un alias de dic2 :

>>> a ={"zwin":3}
>>> b =a
>>> b["panne"] =4
>>> a ; b
{'zwin': 3, 'panne': 4}
{'zwin': 3, 'panne': 4}

Pour seulement transférer les valeurs de a dans b, utiliser b =dict(a)

5.5 Méthodes pour dictionnaires

L'appel à une clé inexistante dans un dictionnaire avec dico[cle] génère une erreur. Il est prudent de prévoir une condition contenant la méthode suivante :

dico.get(cle) renvoie None si la clé n'est pas définie
dico.get(cle,"clé inexistante") retourne la chaîne prévue si la clé n'est pas définie

Il est plus simple d'utiliser le mot-clé in pour ce contrôle :

if 'a' in dico :
  val =dico['a']

En python2, flag =dico.has_key(clef) renvoyait True si le dictionnaire dico contient la clé clef

dico[cle] =valeur ajoute une valeur associée à une nouvelle clé au dictionnaire dico ou modifie la valeur associée à cette clé
dico.pop(clé) renvoie et supprime la valeur définie par une clé (ainsi que la clé)
dico.popitem() renvoie une paire (clé-valeur) et la supprime du dictionnaire. Il faut se rappeler qu'un dictionnaire n'est pas une collection ordonnée, et la méthode popitem() ne renverra peut-être pas la dernière paire clé:item rentrée.

dico.clear() supprime tous les éléments du dictionnaire dico
dic1.update(dic2) ajoute les occurrences du dictionnaire dic2 au dictionnaire dic1, en écrasant les valeurs du dictionnaire dic1 par celles de dic2 pour les clés communes aux deux dictionnaires. L'intuitif dic1 +=dic2 n'est pas permis !

dic2 =dic1 donne un deuxième nom au même objet : modifier l'un modifie l'autre.
dic2 =dic1.copy() copie un dictionnaire dans un autre, les modifications de l'un n'affectent pas l'autre.

dico.keys() crée un objet itérable des clés du dictionnaire dico (<class 'dict_keys'>)
dico.values() crée un objet itérable des valeurs du dictionnaire dico (<class 'dict_values'>)
dico.items() crée un objet itérable des tuples du dictionnaire dico (<class 'dict_items'>)

En python2, les méthodes keys(), values() et items() renvoient des listes (<class 'list'>).

Pour obtenir une liste des clés, il suffit d'utiliser list() : list(dico.keys()), mais ce n'est pas souvent nécessaire, puisque l'objet est itérable.

dico ={'a':1, 'b':2, 'c':3}
for i in dico.keys() :
  print(i)

sum(mondico) renvoie la somme des clés du dictionnaire mondico, une erreur si elle ne sont pas toutes numériques
sum(mondico, n) ajoute n à la somme des clés de mondico

Pour la sommation des valeurs (toutes numériques) d'un dictionnaire : sum(mondico.values())

Pour inverser les clés et les valeurs d'un dictionnaire, il est possible d'utiliser une définition en compréhension :

>>> dico ={ "a":1 , "b":2, "c":3 }
>>> inv ={ i:val for val, i in dico.items() }
>>> inv
{1: 'a', 2: 'b', 3: 'c'}

Quelques remarques sur ce procédé :

5.6 Ensembles {,}

Pour les généralités sur les variables, voir la section variables et assignations.

Python propose depuis sa version 2.3 une classe d'«ensembles», qui sont des collections non ordonnées ! d'éléments uniques.

>>> {'K',3,2,2,4}
set(['K', 2, 3, 4])

Les doublons sont automatiquement éliminés, ce qui peut être utile pour enlever les doublons d'une liste.

Les ensembles peuvent être définis à partir d'une liste, chaîne ou d'un tuple ou dictionnaire (dans ce dernier cas, seules les clés, qui sont uniques, sont considérées).

>>> set("eggs") ; set({"a":3,"b":6})
set(['s', 'e', 'g'])
set(['a', 'b'])

En Python, une collection ne peut pas être élément d'un ensemble :

>>> set([1,{2,3}])
TypeError: unhashable type: 'set'

Il existe une exception pour les chaînes : les caractères d'une chaîne seule seront autant d'éléments (hormis les doublons) de l'ensemble, mais plusieurs chaînes seront autant d'éléments :

>>> set("eggs") ; set(['spam',"eggs"])
set(['s', 'e', 'g'])
set(['spam','eggs']))

nv =s.copy() copie un ensemble dans un autre
s.clear() vide l'ensemble
len(s) renvoie le nombre d'éléments de l'ensemble

Méthodes pour ensembles

s.add(x) ajoute l'élément x s'il ne s'y trouve pas encore
s.discard(x) enlève l'éventuel élément x de s
s.pop() enlève un élément au hasard, KeyError générée si l'ensemble est vide
s.remove(x) enlève l'élément x, KeyError générée si x n'appartient pas à s.

x in s retourne True si l'élément x appartient à s (condition permettant d'éviter KeyError)
a.issubset(b) (ou a<=b) retourne True si a est contenu dans (ou est égal à) b
a.issuperset(b) (ou a>=b) retourne True si a contient (ou est égal à) b

a.union(b) (ou a|b) retourne les éléments de a ou b
a.update(b) (ou a|=b) ajoute les éléments de b à a
a.intersection(b) (ou a&b) renvoie les éléments communs à deux ensembles
a.intersection_update(b) (ou a&=b) ne conserve à a que les éléments communs aux deux ensembles
a.difference(b) (ou a-b) renvoie les éléments de a n'appartenant pas à b
a.difference_update(b) (ou a-=b) retire à a tous les éléments communs avec b
a.symmetric_difference(b) (ou a^b) retourne les éléments non commun à a et b
a.symmetric_difference_update(b) (ou a^=b) retire à a tous les élément communs avec b

frozenset() permet la définition d'ensemble fixes, et ne permet donc pas les modifications par les méthodes clear(), add(), pop(), discard(), remove() ni update()

Note : la méthode + n'est pas définie pour les ensembles. Additionner les éléments des deux ensembles en ne comptant qu'une fois les éventuels éléments communs se fait avec la méthode union() ou l'opérateur |

5.7 Génération de collections

Révision 2023.01.11

range() et générateurs

range(debut, fin, pas) crée une collection à partir d'une progression arithmétique finie ne comprenant pas le nombre fin. Il est possible d'itérer cette collection, ou de la transformer en liste pour la visualiser :

>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(5, 10))
[5, 6, 7, 8, 9]
>>> list(range(3, 27, 4))
[3, 7, 11, 15, 19, 23]
>>> list(range(10,0,-1))
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

Le type d'objet produit est class range.

En python2 range() créait un objet de type 'list'. Il existait également xrange() qui créait un objet itérable 'xrange' capable de délivrer un seul élément à la fois, pour économiser la mémoire. Python3 a supprimé range() de python2 mais a gardé ce nom pour réaliser ce que xrange() faisait en python2. range() de python2 s'écrit maintenant list(range()) en python3.

Un générateur est une collection autre qu'une progression arithmétique :

>>> type(x **3 for x in range(10))
<class 'generator'>

qu'il est possible d'utiliser en itération dans une boucle for :

>>> for i in (x **3 for x in range(4)) : print(i)
…
0
1
8
27

Collection en compréhension

Pour d'autres type de suites, on utilise les collections en compréhension. Pour une liste ([]) de carrés (x **2) des valeurs (x) variant de 0 à 9 (range(10)) :

>>> [x **2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Note : comme les variables locales définies à l'intérieur d'une fonction, une variable utilisée dans une définition en compréhension n'interfère pas avec une éventuelle variable homonyme :

>>> x =43
>>> a =[x for x in range(1, 11)]
>>> a ; x
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
43

Il est possible d'imbriquer des boucles :

>>> [x *y for x in range(1,3) for y in range(7)]
[0, 1, 2, 3, 4, 5, 6, 0, 2, 4, 6, 8, 10, 12]

Cette liste est composée des résultat de la multiplication de x et y, x vaut 1, puis 2, pendant que y vaut successivement les valeurs de 0 à 6. Il en possible de filtrer les résultats par une condition (les multiples de 3 sont ici éliminés) :

>>> suite =[x *y for x in range(5) for y in range(7) if x *y %3 != 0]

résume

suite =[]
for x in range(5) :
  for y in range(7) :
     if x *y %3 !=0 :
       suite +=[x *y]

Réponse :

[1, 2, 4, 5, 2, 4, 8, 10, 4, 8, 16, 20]

Générer une chaîne

Pour générer une chaîne, il suffit de joindre (join) les résultats transformés (str) en chaînes (", " sépare les chiffres) :

>>> ", ".join(str(x **3) for x in range(10))
'0, 1, 8, 27, 64, 125, 216, 343, 512, 729'

Générer un ensemble

Pour générer un ensemble, on utilise les {accolades}, les doublons sont supprimés, et l'ordre n'est pas garanti :

>>> {x *y for x in range(5) for y in range(7) if x *y%3 != 0}
set([1, 2, 4, 5, 8, 10, 16, 20])

Générer un dictionnaire

Les accolades sont également utilisées pour générer un dictionnaire, mais la syntaxe change, pour prendre en compte les couples clé:valeur

>>> {x : chr(96 +x) for x in range(1,6)}
{1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}

5.8 Méthodes pour collections

Dénombrement

len() renvoie le nombre d'éléments d'une collection (tuple, liste ou ensemble), le nombre de doublets clé:valeur d'un dictionnaire ou le nombre de caractères d'une chaîne.

Sommation

sum([1, 2, 3, 4]) renvoie la somme des éléments contenus dans une collection seulement composée de nombres
sum([1, 2, 3, 4], 33) renvoie 43, un nombre initial pouvant être ajouté

Dans l'exemple suivant, la sous-liste [2,6] ne peut pas être ajoutée aux élément 3 et 5.

>>> sum([3,[2,6],5])
TypeError: unsupported operand type(s) for +: 'int' and 'list'

Pour les dictionnaires, la sommation porte sur les clés. Pour qu'elle porte sur les valeurs : sum(mondico.values())

Comparaisons

La comparaison entre collections se pasent différemment selon le type de collections. Pour deux listes, c'est le premier élément qui est considéré, puis le deuxième, etc., ensuite la longueur si tous les éléments de l'une correspond à tous les premiers de l'autre :

>>> [1,2,3] < [2,1]
True
>>> [1,2,3,4] > [1,2,3]
True

Pour les ensembles, < signifie l'inclusion stricte, > la contenance stricte :

a>b retourne True si a contient b et comprend au moins un autre élément
a<b retourne True si a est contenu dans b, lequel comprend au moins un élément supplémentaire

>>> {2,1} < {1,3,2}
True

La comparaison est interdite entre dictionnaires.

python2 admettait la comparaison de dictionnaires, par paire clé/valeur et selon leurs longueurs :

>>> {1:3, "b":3} < {"d":4, 1:3}
True
>>> {1:3, "b":3, "a":12} < {"d":4, 1:3}
False

x in y retourne True si x est un élément de y (contrairement aux chaînes, où x in y vérifie que x est une plage de y)

max(x) renvoie le plus grand élément d'une collection
min(x) renvoie le plus petit élément d'une collection
max(x,y) renvoie la collection la plus «grande»
min(x,y) renvoie la collection la plus «petite»

max() et min() ne fonctionnent pas pour comparer deux dictionnaires, mais bien en python2.

cmp(x, y) qui renvoie -1 si x<y, +1 si x>y et 0 si x ==y est suprimée en python3. Voir la recette pour une définition de la fonction cmp() .

Tester

any() retourne True si au moins un élément d'une collection est vrai, c'est-à-dire différent de 0, None, False, "", [], () ou {}.

>>> any([0, '', {}])
False

La liste suivante contient la chaîne "0", qui n'est pas vide.

>>> any(["0", '', {}])
True

all() retourne True si aucun des éléments n'est «faux» (voir any() ci-dessus) :

>>> all([3, "hey", [43]]) ; all(([], [2]))
True

La liste suivante contient trois éléments non faux, à savoir 3, [3,"eggs",0] et "spam" (même si [3,"eggs",0] contient l'élément 0).

>>> all([3, [3, "eggs", 0], "spam"])
True

Attention :

all([]) retourne True parce qu'une liste vide ne contient aucun élément faux (0, "", [ ]…)
all([[]]) retourne False parce que la liste contient une liste vide
all([[0]]) retourne True parce que la liste contient une liste non vide

Énumérer

enumerate(coll) génère une objet enumerate formé des paires (numéro d'ordre, élément) à partir d'une collection. Dans le cas d'un dictionnaires, ce sont les clés qui forment la seconde valeur de la paire.

>>> list(enumerate({"a":1, "b":3, "d":9}))
[(0, 'a'), (1, 'b'), (2, 'd')]

Il est possible d'énumérer un ensemble, même si ce n'est pas une séquence.

>>> list(enumerate(set("eggs")))
[(0, 'g'), (1, 's'), (2, 'e')]

À partir de Python2.6, on peut ajouter un début :

>>> list(enumerate([4,6,7],start =1000))
[(1000, 4), (1001, 6), (1002, 7)]

Tri

sorted(coll, key, reverse=False) renvoie (toujours) une liste triée des élements d'une collection (pour les dictionnaires, il s'agit des clés) :

>>> sorted(["az", "vD", "Ez"])
['Ez', 'az', 'vD']

Pour un tri sans considération de casse (pour les chaînes et listes de chaînes), key =str.lower :

>>> sorted(["az", "vD", "Ez"], key =str.lower)
['az', 'Ez', 'vD']

Pour une sortie inversée (sans définir cmp ni key) :

>>> sorted([4,2,1,3], reverse=True)
[4, 3, 2, 1]

Enfin, en UTF-8, pour un tri «naturel» c'est-à-dire mélangeant majuscules et minuscules, lettres accentuées ou non (merci à Tyrtamos) :

import locale
locale.setlocale(locale.LC_ALL,'')
print(sorted(["e", "â"], key =locale.strxfrm))

Une manière utilisant le module icu (à installer) est disponible dans la page des modules.

Inverser

reversed() renvoie un itérateur formé de l'inversion d'une collection (il s'agit d'un objet "reverse", qui n'est pas affichable avec print, ni découpable avec [m:n] : on ne peut que le parcourir avec in) :

>>> for i in reversed((12,56,34,78)) : print(i,end =" ")
78 34 56 12

tuple(reversed((12,56,34,78))) pour le récupérer en tuple :

Une chaîne de caractère étant un tuple de caractères, il est possible de la renverser, en recollant ensuite les caractères avec join :

>>> print("".join(reversed("azerty")))
ytreza

"azerty"[::-1] est plus simple (et rapide) et ne demande pas à convertir l'objet <reverse> en type de départ :

>>> li =[1, 2, 3, 4, 5] ; li =li[::-1] ; print(li)
[5, 4, 3, 2, 1]

Dictionnaires et ensembles ne peuvent être inversés, n'étant pas des séquences :

>>> reversed(set(["a",1,"b",2])
TypeError: argument to reversed() must be a sequence
>>> {"a":1, "b":2}[::-1]
TypeError: unhashable type

Fonctions indésirables

Guido Van Rossum se repent d'avoir laisser implémenter quelques fonctions, surtout parce qu'elles sont très contournables.

map(fonction,variable) applique une fonction à chaque élément d'une collection, en l'occurrence, les caractères d'une chaîne. Le résultat est un objet itérable :

>>> list(map(ord,'python'))
[112, 121, 116, 104, 111, 110]

Cette fonction peut facilement être remplacée par une liste en compréhension :

[ord(x) for x in "python"]

En Python2, map() renvoie directement une liste.

filter(fonction, liste) renvoie des éléments de tuple, liste, clés de dictionnaire, filtrés par une fonction, éventuellement créée pour l'occasion avec lambda, dans un objet itérable :

>>> list(filter(lambda x : x%2 ==1, range(10)))
[1, 3, 5, 7, 9]

Cette fonction peut facilement être remplacée par une liste en compréhension :

[x for x in range(10) if x%2 ==1]

En Python2, filter() renvoie directement une liste.

À condition que le module functools soit importé, reduce(fct, lst) réduit une séquence : liste, tuple, clés de dictionnaire, ensemble… par une fonction à deux arguments. Dans l'exemple, la fonction lambda définit une multiplication, qui sera appliquée aux éléments de la liste [1,2,3,4,5,6], produite par range(1,7) (il s'agit donc de la factorielle de 6).

>>> import functools
>>> functools.reduce(lambda x, y : x *y, range(1, 7))
720

Guido Van Rossum propose de remplacer reduce() par une boucle :

>>> acc =1
>>> for i in range(1,7) : acc*=i
…
>>> print(acc)
720

En Python2, reduce() est une fonction interne et ne doit pas être importée.

zip(coll_1,coll_2,…) renvoie une liste de tuples : le premier tuple rassemble tous les premiers éléments des collections (chaînes de caractères, tuples, listes, dictionnaires ou ensembles), le deuxième tuple tous les deuxièmes éléments, etc. :

>>> print(zip("abcde",(1,2,3,4,5,6,7),['u','v','w','x','y','z']))
[('a', 1, 'u'), ('b', 2, 'v'), ('c', 3, 'w'), ('d', 4, 'x'), ('e', 5, 'y')]

La liste des tuples est limitée à la longueur de la plus petite collection.

6. Entrées et sorties

6.1 Saisies

input permet la saisie d'une chaîne.

>>> input("What's your quest?")
What's your quest?

En Python2, raw_input() sert à saisir une chaîne, et input() évalue une expression : un calcul ou une commande saisie est exécutée (il faut donc l'utiliser avec précaution) :

>>> input()
open("essai.txt", "w").write("See you soon!") # à saisir

écrase les données de l'éventuel fichier essai.txt !

Pour une fonction permettant la saisie des touches de fonctions et flèches, voir le module curses.

Saisie d'expression évaluables Rév. 2023.01.11

eval() évalue une expression Python exprimée sous forme de chaîne :

>>> eval("3 *8")
24

Combiné avec input(), eval()peut transformer une chaîne saisie en résultat :

>>> eval(input("Une fraction: "))

Il peut s'agir d'une fonction :

>>> eval("'Je vous ai compris !'.split()")
["Je", "vous", "ai", "compris", "!"]

Ne pas confondre eval() avec exec(), qui peut exécuter une série d'instructions contenues dans une chaîne ou dans un script sous forme de fichier.

Une saisie multiple est possible avec eval(input()) :

>>> a, b, c =eval(input("entrer trois nombres séparés par des virgules: "))
1, 2, 3 # à entrer!
>>> a
1
>>> b
2
>>> c
3

6.2 Affichages Rév. 2021.01.21

Pour l'affichage à un endroit particulier de l'écran, voir le module curses et les séquences ECMA-48, qui permettent également certaines couleurs.

print("Ni!", 123) affiche la chaîne suivi du nombre
var =123 ; print(var, var *5)
var2 =123 ; print("Le double de", var2, "est", var2 *2)

Par défaut, la séparation des chaînes est l'espace et la sortie génère un saut de ligne (\n). Le paramètre sep ="" permet de supprimer l'espace ou de le remplacer par une chaîne de caractères.

>>> print('Nombre', 10, sep ="-*-")
Nombre-*-10

Pour supprimer le saut de ligne, utiliser le paramètre end ="" :

>>> import time
>>> for i in range(5) :
>>>   print(i, end ="") ; time.sleep(1)
01234

Attention : une suite de print(chaine, end ="") ne sera affichée qu'à partir du print() suivant contenant un saut de ligne. Pour imprimer effectivement une chaîne sans retour à la ligne, utiliser flush =True. Cela permet par exemple une barre de progression horizontale :

>>> import time
>>> for i in range(5) :
>>>   print("-", end ="", flush =True) ; time.sleep(1)

À partir de python2.6, on peut utiliser print() grâce à from __future__ import print_function (première ligne du script ne commençant pas par '#'), mais le paramètre flush n'est pas disponible. On utilise sinon le mot réservé print :
print "Eggs & spam" au lieu de print("Eggs & spam") (avec saut de ligne)
print (("Eggs","Spam")) pour afficher le tuple ('Eggs', 'Spam')

repr(objet) représente un objet sous forme de chaîne, par exemple pour le stoker dans un fichier. Voir eval() pour l'opération inverse) :

>>> a ="C'est déjà ça"
>>> a ; print(a) ; print(repr(a))
"C'est déjà ça"
C'est déjà ça
"C'est déjà ça"

En python2 / UTF-8, cela donne :

>>> a ="C'est déjà ça"
>>> a ; print(a) ; print(repr(a))
"C'est d\xe9j\xe0 \xe7a"
C'est déjà ça
"C'est d\xe9j\xe0 \xe7a"

Ce codage \#e0 a été retenu pour les octets-caractères non-ASCII du type bytes.

6.3 Fichiers-textes

Attention ! Les différents systèmes n'utilisent pas le même signalement de fin de ligne (en fait fin de paragraphe) : octet 13 pour Mac avant OS X, octet 10 pour Unix (et OS X) et les deux octets 13 et 10 pour le DOS et Atari. L'ouverture de fichiers textes avec "r ou "w" remplace s'il le faut les fins de ligne de tous les systèmes par le "\n" de Unix. Ce n'est que si vous voulez sauvegarder ou charger un fichier texte avec les modes "rb" ou "rw" (quelles que que soient vos raisons) que la fin de ligne a son importance selon les systèmes.

Python2.7 n'utilise les fins de paragraphe en \n que pour les systèmes Unix. Il faut spécifier les octets \r pour l'Amiga et le Mac Classic, et \r\n pour Atari, MS-Dos et Windows.

Le module 1.3 os permet également de manipuler les fichiers. Voir égalemement 2.7 Structure with + as

descr =open("/chemin/fichier") ouvre un fichier en lecture, descr est ici son descripteur, et c'est à partir de cette variable que vous pourrez lire, écrire, ajouter… des données avant de refermer le fichier avec cette variable :

>>> descr =open("votrefichier")
>>> type(descr)
<class '_io.TextIOWrapper'>
>>> print(descr)
<_io.TextIOWrapper name='votrefichier' mode='r' encoding='UTF-8'>

C'est sur le descripteur que s'appliquent les méthodes suivante :

descr.mode renvoie le mode d'ouverture du fichier ('r' par défaut)
descr.closed est vrai (True) si le fichier est fermé, False sinon
descr.name renvoie le nom du fichier
fich.fileno() est un numéro d'ouverture de fichier

descr.close() referme un fichier ouvert et enregistre un fichier créé ou édité ("w")

En python2, file() était un équivalent de open().

Lire un fichier

fd =open("/chemin/fichier", "r") ouvre un fichier en lecture seulement (mode par défaut : "r" n'est pas obligatoire
chaine =fd.read() charge entièrement le fichier dans une variable
chaine =fd.read(n) ne charge qu'un nombre limité de n octets, en positionnant le pionteur sur l'octet n : il est possible de lire le fichier par morceaux.

fd.readline() lit une ligne (délimitée par une fin de paragraphe) d'un fichier texte et se place sur la suivante pour un appel ultérieur (le plus souvent utilisé dans une boucle)
liste =fd.readlines() (avec s) place toutes les lignes dans une liste, \n compris

Il existe une syntaxe très simple pour traiter une à une les lignes d'un fichier-texte :

descr =open("monFichier.txt", "r")
for ligne in descr :
  print(ligne, end ="")       # pour ne pas ajouter une nouvelle ligne '\n'

ou même

for ligne in open("monFichier.txt", "r") :
  print(ligne)

…ce qui rend readline() inutile.

Il s'agit de texte, quel que soit l'encodage utilisé. UTF-8 permet donc les caractères accentués, idéogrammes, symboles, caractères semi-graphiques, émoticones…

Éditer un fichier

descr =open("/chemin/fichier", "w") crée ou ouvre un fichier en écriture (texte), écrasant un fichier de même nom (Attention : sans demande de confirmation ! par sécurité, prévoyez pour le fichier à sauvegarder un autre nom que le fichier d'entrée)
descr.write(chaine) écrit une chaîne dans un fichier, représenté par descr
descr.writelines(liste) écrit toutes les chaînes d'une liste
descr.close() ne pas oublier de refermer, et donc enregistrer, un fichier édité

Notes :

Les modifications s'opèrent dans une variable-tampon, pas directement sur le disque. Donc :

descr.close() enregistre et ferme un fichier édité
descr.flush() force l'enregistrement, sans refermer le fichier

Une autre façon est d'utiliser la structure with … as …

with open("python.txt", "w") as descr :
  descr.write("Eggs & Spam!")

…le fichier étant automatiquement refermé à la sortie de la structure.

descr =open("/chemin/fichier", "r+") ouvre un fichier en lecture et écriture

Ajout à un fichier texte

descr =open("/chemin/fichier","a") ouvre un fichier en ajout d'écriture, et le crée s'il n'existe pas encore. Idéal pour un fichier log.

Il est possible de rediriger les sorties print vers un fichier-texte en utilisant le module sys.

Mais cela semble plus simple en avec file =descr

with open("mon_fichier.txt", "a") as descr : # ouverture en ajout
  print([1,[2,3],4], file =descr)

ou

print("Ajout d'une chaîne", file =open("monfichier.txt", "a"))

descr =open(nom, "a+") ouvre un fichier en lecture et ajout

En python2 :

#! /usr/bin/python2.7
descr =open("monFichier.txt", "a") # ouverture en ajout d'un fichier
li =[1,[2,3],4]
print >> descr, li # sortie vers monFichier.txt (avec fin de ligne)
descr.close() # inscrit les données et ferme le fichier

Tous ces modes utilisent l'UTF-8 par défaut. Pour charger un fichier préalablement sauvegardé en iso8859-1, il faut préciser l'encodage :

with open("mon_fichier.txt", "r+", encoding="latin-1") as descr :
  print(descr.read())

Cela n'est pas nécessaire pour les fichiers sans accent puisque l'ASCII (avec des octets de 32 à 127 + 9, 10 et 13) est un sous-ensemble de l'ISO8859 et de l'UTF-8.

Note :

6.4 Fichiers binaires et relatifs

Fichiers "binaires"

Dans un fichier «binaire», les 256 octets possibles peuvent être écrits ou lus. Les données sont passées sous la forme d'un objet bytes. Il faut spécifier le mode d'ouverture b (pour binaire) : rb, wb, ab rwb, éventuellement suivis de + :

data =bytes([0, 255, 178, 56, 94])
descr =open("dummy.bin", "wb")
descr.write(data)
descr.close()

Pour lire un tel fichier :

descr =open("dummy.bin","rb")
data =descr.read()
descr.close()
print(data)

Voir également le module os permettant de manipuler les fichiers.

Fichiers "relatifs"

Les fichiers relatifs ("random access") sont des fichiers binaires directement accessibles à n'importe quel endroit et pour une quantité précisée :

descr =open("fichier.dat", "rb")
octets1 =descr.read(16)
octets2 =descr.read(20)
descr.close()

octets1 contient les 16 premiers octets, octets2 les 20 suivants… un pointeur ayant conservé le décalage résultat de la lecture des 16 premiers octets. Le système est le même en mode écriture, mais soyez attentif à bien introduire des objets bytes :

octets1 ="a\x01b\x02" ; octets2 ="c\x03d\x04e\x05"
descr =open("fichier.dat", "rw")
descr.write(octets1)
descr.write(octets2)
descr.close()

Il est possible de pointer un endroit particulière avant de commencer à lire (ou à écrire) dans un tel fichier :

descr.seek(43, 0) pointe le 44e octet (le premier est le décalage 0) à partir du début du fichier (positionnement absolu ; ,0 est facultatif)
descr.seek(13,1) pointe 13 octets plus loin, à partir de la position courante (1 : positionnement relatif)
descr.seek(5,2) pointe 5 octets vers le début du fichier (2 : positionnement relatif rétrograde)
descr.seek(-100) pointe 100 octets avant la fin fichier

descr.tell() retourne le décalage courant

Notes : le fichier s'étend selon les besoins : un seul octet écrit au décalage 10 **6 générera un fichier d'un mega +1 octets ; les octets non écrits sont des octets vides.

Voir la recette sur l'utilisation de tels fichiers.

7. Fonctions «utilisateur»

En mathématique (analyse), une fonction retourne une et une seule valeur numérique. Pour beaucoup de langages de programmation, les «fonctions» peuvent renvoyer plusieurs valeurs, une chaîne, l'adresse d'un tableau, voire ouvrir un fichier ou imprimer un message d'erreur.

Les noms de fonction suivent les mêmes règles que les noms de variable.

En Python, une fonction est toute partie de code qui peut être écrit en dehors d'une structure et qu'il est possible d'appeler de n'importe quel endroit du programme. Il est même possible de les écrire dans un autre fichier, appelé module, que l'on pourra importer (voir modules utilisateurs).

Les fonctions servent à ne pas répéter le même code à plusieurs endroit du programme, ce qui constitue un gain de place, permet une maintenance plus simple et une lecture plus globale, le coeur du programme pouvant être une séquence très courte et assez explicite. À condition de prévoir de façon adéquate les fonctions lecture(), trouver_liens(), ajout() et suivant(), le noyau d'une application peut ressembler à ceci :

cpt =0
while True
  page =lecture("fichier"+str(cpt))
  liens =trouver_liens(page)
  sortie =ajout("fichiersortie", liens)
  cpt +=1
  suivant()

Certains mots sont réservés à python et ne peuvent donc pas être utilisés comme nom de fonction (ou de variable) : and - as - assert - break - class - continue - def - del - elif - else - except - exec - finally - for - from - global - if - import - is - lambda - not - or - pass - raise - return - try - while - with - yield

À partir de python2.6, with et as sont également réservés. Ils le sont également en python2.5 en cas de spécification from __future__ import with_statement sur la première ligne ne commençant pas par '#').

En python2, print et exec sont des mots réservés et non des fonctions().

7.1 Fonction anonyme lambda

lambda x : permet une définition simple de fonction :

carre =lambda x : x **2
print(carre(5))

Les fonctions anonymes permettent également de définir une fonction à l'intérieur d'une instruction de Python.

>>> filter(lambda x : 117 > ord(x) > 111, "python")
'pt'

Cette écriture peut être remplacée par une liste en compréhension :

>>> "".join([x for x in "python" if 117 > ord(x) > 111])

qui peut se traduire : joindre les lettres contenues dans la chaîne 'python' à condition que leur code ASCII se situe entre 111 et 117.

Note : La fonction lambda est conservée en python3, malgré le vœu de Guido Van Rossum de l'abandonner.

7.2 Fonction classique def

def fonction(arg1, arg2…) permet la définition d'une fonction définie par l'utilisateur. La valeur envoyée dans la fonction peut être un nombre, une variable ou une autre fonction. La valeur est reçue dans la définition de la fonction par une autre variable (ici arg) multipliée par deux et affichée à l'écran. Exemple :

def double(arg) :
  print(arg *2)
print(double(5))

Il est possible de définir une valeur par défaut. La réponse de l'exemple suivant sera 20 parce qu'aucune valeur n'est précisée dans l'appel :

def double(arg =10) :
  print(arg *2)
double()

La définition de la fonction doit être placée avant l'appel. L'exemple suivant retournera une erreur, affiche() n'étant pas connu de l'interpréteur lorsque celui-ci rencontre sortir() :

def sortir(nbr) :
  affiche(str(nbr) *nbr) # le nombre répété nbr fois sous forme de chaîne

sortir(5)

def affiche(chaine) :
  print(chaine)

Dans cette correction de script, même si la fonction affiche() suit la fonction sortir(), elle est connue de l'interpréteur lorsque celui-ci rencontre sortir() :

def sortir(nbr) :
  affiche(str(nbr) *nbr) # le nombre répété nbr fois sous forme de chaîne

def affiche(chaine) :
  print(chaine)

sortir(5)

return

return arrête une fonction (par exemple dans une condition) et retourne la valeur None
return expression arrête la fonction et retourne la valeur (ou un tuple si les valeurs sont multiples)

def double(var) :
  return var *2
for i in range(1, 11) :
  print(double(i))

Dans le cas où plusieurs variables par défaut sont définies, il est possible de préciser la variable que l'on passe :

def mult(x =1, y =10) :
  return x *y
print(mult(x =3))
print(mult(y =4))

Variables locales et globales

Une variable initialisée à l'intérieur d'une fonction est locale : elle est séparée de celles utilisées dans le reste de l'application ou initialisées dans d'autre fonctions. Remarquez la différence entre les deux print(ch) :

def chaine() : # affiche 'eggs'
  ch ="eggs"
  print(ch)

ch ="spam"
chaine()  # affiche 'eggs'
print(ch) # affiche 'spam'

Si l'on veut qu'une variable initialisée dans une fonction soit utilisable par le reste de l'application (et dans d'autres fonctions), il faut indiquer juste après la ligne def l'instruction global reprennant la liste des variables globales séparées par des virgules (global var1, var2, var3 pour plusieurs variables globales).

def chaine() :
  global ch
  ch ="eggs"

ch ="spam"
chaine()  # la fonction chaîne() modifiera la variable globale ch
print(ch)

Passage d'arguments spéciaux

Un ensemble de valeurs sera reçu comme un tuple si la variable de réception d'une fonction est préfixée par * (sans quoi il y aurait trop de valeur pour la seule variable) :

def quoi(*var) :
  print(var)
  print(type(var))
quoi(1, 2, 3)

…ce qui renvoie :

(1, 2, 3)
<type 'tuple'>

Une suite d'affectations sera reçue comme un dictionnaire si la variable de réception est préfixée par ** :

def quoi(**var) :
  print(var)
  print(type(var))
quoi(a=1, b=2, c=3)

…ce qui renvoie :

{'a':1, 'c':3, 'b':2}
<type 'dict'>

Déjà disponible en python2, cette syntaxe est destinée à remplacer l'appel apply(quoi, (), {}) qui n'existe plus en python3.

Récursivité

Une fonction peut s'appeller elle-même (récursivité). Il est alors indispensable de prévoir (au moins) une sortie :

def fact(x) :
  if x ==0 : return 1
  return x *fact(x -1) # la fonction s'appelle elle-même

print(fact(10))

…la valeur étant décrémentée jusqu'à 0 ; à ce moment, le calcul x *(x-1) *(x-2)… *1 est effectué et retourné.

Fonction locale

Il est possible de définir une fonction locale, en l'incluant dans une autre fonction. Cette fonction locale ne peut être appelée en dehors de la fonction qui l'inclut :

def euler(max) :
  def fact(x) :
    if x ==0 : return 1
    return x *fact(x -1)
  somme =0
  for k in range(max) :
    somme +=1 /fact(k)
  return somme

print(euler(16))
print(fact(5)) # déclenche l'erreur NameError: name 'fact' is not defined

En python2, somme +=1. /fact(k) pour que le résultat ne soit pas entier.

Modification de fonctions interne à python

Il est possible de modifier les fonctions internes de Python en les redéfinissant : int(), float(), complex(), oct(), hex(), len(), abs(), divmod() en redefinissant ces fonctions.

Si l'on désire que la fonction len() retourne la longueur en octets plutôt qu'en caractère :

def len(x) :
   long =0
   if type(x) ==type("") : # seulement pour les chaînes
     x= bytes(x, "utf-8")
   for i in x :
     long +=1
   return long

…quoiqu'il vaudrait mieux créer une fonction-utilisateur ayant son propre nom.

Note : c'est impossible pour les mots réservés.

En python2, coerce() peut être modifié.

7.3 Génération avec yield

Il est possible d'utiliser une fonction pour générer une série de valeurs, stockées une à une par l'instruction yield. L'exemple suivant donne les approximations successives (16 termes demandés dans l'appel) du nombre e, par la formule Σ(1/x!), soit 1 +1 +1/2 +1/6 +1/24… vers 2,71828…

def fact(x) : # ceci est une fonction 'utilisateur' classique
  if x==0 : return 1
  return x *fact(x -1)

def euler(max) :
  somme =0
  for k in range(max) :
    somme +=1 /fact(k)
    yield somme       # l'instruction yield engrange la valeur

for i in euler(16) :  # les 16 approximations successives de 'e' par la formule d'Euler
  print(i)

print(type(euler(16))) # confirmation que euler(16) est bien de type 'generator'

En python2, l'instruction yield n'est pleinement disponible que depuis la version 2.3 ; avec la version 2.2 il est nécessaire de préciser en début de programme (future est précédé et suivi de deux tirets bas, et doit figurer sur la première ligne ne commençant pas par '#') :

from __future__ import generators

7.4 Modules 'utilisateur'

Voir ici pour des informations plus précise sur les modules.

Il est possible de regrouper des fonctions qui seront utilisées par plusieurs applications dans un fichier (par exemple monmodule.py, l'extension .py est nécessaire) que l'on appelle dans une application avec import monmodule (sans .py). Sauvegardons par exemple les deux fonctions déjà vues plus tôt, dans le fichier matsup.py :

#! /usr/bin/python
# écrit en python2 2006.12.20 -- réécrit en python3.7.3 -- www.jchr.be -- copyleft GPL 2 --
"""MATSUP : un module juste pour essayer"""

# définition d'une constante
e =2.7182818

def fact(n) :
  """Renvoie la factorielle d'un nombre : 1, 1, 2, 6, 24, 120…"""
  if n ==0 : return 1
  else : return n *fact(n -1)

def euler(i) :
  """Valeur approchée de 'e' après 'i' itérations : 1, 2, 2.5, 2.66…, 2.70833…"""
  somme =0
  for k in range(i) :
    somme +=1 /fact(k)
  return somme

Dans le mode interactif, importons-le, et interrogeons-le :

>>> import math, matsup
>>> matsup.euler(10)
2.7182815255731922
>>> matsup.e
2.718281828
>>> import math
>>> math.e
2.7182818284590451

Vous avez la possibilité (et le devoir) de commenter votre module """dans chaque fonction""" :

>>> help(matsup.fact)
fact(n)
  """Renvoie la factorielle d'un nombre : 1, 1, 2, 6, 24, 120…"""

Essayez également help(matsup) et help(matsup.euler).

On annule un module avec del module ou del(module)

Notes

del module décharge un module. Attention : l'importation d'un module fabrique sa compilation sous l'extension .pyc, dans le sous-répertoire __pycache__. C'est ce fichier sous forme compilée qui sera ensuite chargé.

8. Programmation-objet

La programmation orientée objet (POO) vous permet de définir et utiliser vos propres variables structurées ainsi que leurs comportements. On commence par définir une classe d'objets, c'est-à-dire un objet générique et ses composants :

Les avantages sont nombreux : une fois qu'une variable est instanciée par UneVariable =VotreClasse(paramètres) il en découle une série d'attributs qui auront été définis rien que pour eux, les objets bénéficient de méthodes qui leur sont propres ; il est même possible de redéfinir les opérateurs classiques comme les + , * , ==

8.1 Classe et attributs

Le premier script ci-dessous définit une classe d'individus définis par une hauteur et un poids, et pour lesquels l'indice de masse corporelle sera automatiquement calculé.

La méthode __init__ y réceptionne les valeurs par les paramètres ht et pds. Le paramètre self représentera l'objet dans toute la définition de la classe.

Chaque argument de réception est ensuite fixé à l'objet par self. Pour nouvel objet créé dans le script par une instanciation (par exemple x =individu(178,75)), x.hauteur représentera sa taille et x.poids son poids. Un troisième attribut est aussi calculé : l'indice de masse corporelle (le poids divisé par le carré de la taille, arrondi ici à une décimale), x.IMC.

#! /usr/bin/python3

class individu :
  def __init__(self, ht, pds) :
    self.hauteur =float(ht)/100
    self.poids =float(pds)
    self.IMC =round(self.poids/self.hauteur/self.hauteur, 1)

toto =individu(178,75)
print(toto.hauteur, toto.poids, toto.IMC)

L'exécution de ce premier script de programmation-objet permet de voir que dès que l'objet toto est défini (instanciation), l'attribut IMC est automatiquement calculé et disponible.

8.2 Méthodes

Une classe ne se limite en général pas à la définition de __init__(). L'intérêt de la programmation objet est aussi de définir des méthodes spécifiques aux objets d'une classe. Dans le script qui suit, une autre façon de calculer le poids idéal est défini. On peut appeler la méthode comme s'il s'agissait de la fonction d'un module importé : individu.ideal(toto), mais il est plus pratique d'utiliser toto.ideal(), python sachant que toto appartient à la classe individu, dont ideal() est une méthode.

#! /usr/bin/python3

class individu :
  def __init__(self, sx, ht, pds) :
    """sexe : M =1, F =2 ; hauteur: en mètres ; poids : en kilos"""
    self.sexe =sx
    if (1 >self.sexe or self.sexe >2) :
      raise("1 pour les hommes ; 2 pour les femmes")
    self.hauteur =float(ht)
    self.poids =float(pds)
    self.IMC =round(self.poids /self.hauteur /self.hauteur, 1)

  def ideal(self) :
    taux =1 # calcul pour un homme
    if self.sexe ==2 : taux =.9 # révision à la baisse pour les femmes
    return ((self.hauteur *100 -150) *3 /4 +50) *taux

  def diagnostic(self) :
    if self.IMC <15 : return "- Maigreur extrême (<15)"
    if 15 <=self.IMC <18.5 : return "- Maigreur (15-18,5)"
    if 18.5 <=self.IMC <25 : return "- Poids idéal (18,5-25)"
    if 25 <=self.IMC <30 : return "- Surpoids (25-30)"
    if 30 <=self.IMC <35 : return "- Obésité modérée (30-35)"
    if 35 <=self.IMC <40 : return "- Obésité sévère (35-40)"
    if 40 <=self.IMC : return "- Obésité morbide (>40)"

  def anamnese(self) :
    print("Pour adultes, exceptés sportifs et femmes enceintes ou qui allaitent")
    print("Sexe:", self.sexe, "-", self.hauteur,"m,", self.poids,\
    "Kg - Poids idéal (autre formule) :", self.ideal())
    print("IMC:", self.IMC, self.diagnostic())

toto =individu(1, 1.78, 75)
toto.anamnese()

Notes :

8.3 Surcharge des opérateurs

Python n'additionne pas de la même manière les nombres et des chaînes… La programmation orientée objet permet de redéfinir comment +, -, %, / … doivent agir : c'est ce qu'on appelle «surcharger» un opérateur.

Pour modifier l'addition + entre deux instances d'une classe, on écrit une méthode __add__(self, other) et l'on décide en fin de méthode ce qui sera renvoyé. Ce mode d'addition n'affectera que les objets de la classe dans laquelle il aura été défini. Voici un exemple de surcharge d'opérateur où l'on réécrit la comparaison d'égalité __eq__ pour comparer des indices de masse corporelle avec une tolérance de 5% :

#! /usr/bin/python3

class individu :
  def __init__(self, ht, pds) :
    self.hauteur =float(ht)
    self.poids =float(pds)
    self.IMC =round(self.poids /self.hauteur /self.hauteur, 1)

  def __eq__(self, other) : # redéfinition de l'opérateur '=='
    if abs(self.IMC -other.IMC) /max(self.IMC, other.IMC) <.05 :
      return True
    else :
      return False

a =individu(1.81, 82)
b =individu(1.81, 85)
c =individu(1.81, 89)
print(a.IMC, b.IMC)
print(a ==b ==c)
print(a ==c)

Comme il s'agit d'un test, True ou False est retourné, ce qui permet d'utiliser le test dans une condition : if (a ==b) :

Python est capable, à partir d'une opération binaire, d'enchaîner deux opérations : dans le cas ci-dessus, a ==b ==c renvoie True parce que a ==b et b ==c mais a ==c n'est pas vrai car trop différents.

Méthodes unaires (self)

-__neg__() +__pos__() ~__invert__()

Méthodes de comparaison (self, other)

<__lt__() ==__eq__() >__gt__() in__contains__()
<=__le__() !=__ne__() >=__ge__()

Méthodes binaires classiques (self, other)

+__add__() -__sub__() /__div__() //__floordiv__()
*__mul__() **__pow__() %__mod__() /__truediv__()
&__and__() |__or__() ^__xor__() <<__lshift__()
>>__rshift__()

Méthodes binaires abrégées (self, other)

+=__iadd__() -=__isub__() /=__idiv__() //=__ifloordiv__()
*=__imul__() **=__ipow__() %=__imod__() /=__itruediv__()
&=__iand__() |=__ior__() ^=__ixor__() <<=__ilshift__()
>>=__irshift__()

python2 ne connaît pas __truediv()__

8.4 Autres fonctions

En cours d'écriture

NouvelObjet =object() permet de créer une classe à partir de rien.
isinstance(obj,classe) retourne True si l'objet (instance) appartient à la classe
super() permet de se référer à la classe parente et à utiliser ses méthode sans utiliser son nom
issubclass(sub, classe) retourne True si sub dérive de classe
hasattr(inst, 'attr') retourne True si l'attribut existe pour l'objet
getattr(inst, 'attr') retourne la valeur d'un attribut pour une instance
setattr(inst, 'attr', val) fixe une valeur à l'attribut d'une instance, comme obj.attr =val
delattr(inst, 'attr') détruit l'attribut d'une instance (nom est une chaîne) = del obj.attr
callable(expr) retourne True si l'expression est appelable : les classes et les fonctions internes ou définies par les utilisateurs ou dans les modules (et doit alors éventuellement être préfixées), et False pour les variables ; les mots réservés (for, if, def…) retournent SyntaxError s'il sont entourés de guillemets, une erreur sinon.

9. Introspection

Python permet l'inspection de son propre fonctionnement.

type() retourne le type d'une variable. En cas de test, comparer avec quelque chose de connu :

print(type(var) ==type(0)) # la comparaison type(var) =="<class 'int'>"' ne fonctionne pas !

En python2, type() renvoyait <type 'xxx'> et non <class 'xxx'>

exec() permet d'exécuter du code contenu dans une chaîne ou dans un script python sous forme de fichier :

>>> exec("from math import sin, pi ; print(sin(pi/4))")
0.707106781187
>>> exec(open("monfichier.py").read())

callable(expr) retourne True si l'expression est appelable : les classes et les fonctions internes ou définies par les utilisateurs ou dans les modules (et doit alors éventuellement être préfixées), et False pour les variables ; les mots réservés (for, if, def…) retournent SyntaxError s'il sont entourés de guillemets, une erreur sinon.

dir() liste de fonctions de python dans la portée locale :

['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

Note : dans une fonction, liste les fonctions imbriquées ; dans une classe, liste ses méthodes et attributs.

dir('__builtins__') liste les noms de méthodes et d'attributs définis pour une instance (ici : '__builtins__')

Dictionnaires de variables globales ou locales

vars() est un dictionnaire des variables, où chaque variable est décrite comme une chaîne (son nom) associée à sa valeur .

>>> pi =3.1415926
>>> vars()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__':
<class '_frozen_importlib.BuiltinImporter'>, '__spec__': None,
'__annotations__': {}, '__builtins__':
<module 'builtins' (built-in)>, 'pi': 3.1415926}

Attention ! Son contenu diffère selon l'endroit du script, vars() ne voyant que les variables locales dans une classe ou fonction.

globals() est le dictionnaire des variables globales. En dehors de toute fonction ou de classe, globals() ==vars()

locals() est le dictionnaire des variables locales d'une fonction ou d'une classe. Dans une fonction ou classe, locals() ==vars()

Identifiants de variables et de données

id(var) donne l'identifiant d'une variable. Dans une fonction, une variable locale a un id() différent de son homonyme global. À chaque réaffectation d'une variable, l'identifiant change, comme par exemple la variable de récursion dans une boucle à chaque itération :

for i in range(3) :
  print(id(i))

Note : l'id() d'une fonction se retrouve en hexadécimal dans vars().

hash(var) donne l'identifiant de la donnée contenue dans une variable ; deux variables de même valeur partagent la même valeur "hash".

a =56 **.5 ; b =56 **.5
print(hash(a), hash(b))

A. Documentation

Documentation dans le logiciel Python

Dans le mode interactif (obtenu en saisissant python dans une console), vous en saurez plus sur la licence avec

>>> print(copyright)
>>> print(license())

help rentre dans l'aide interactive
help(fonction) informe sur une fonction (écrite ici sans parenthèse) ou un module interne ou chargé
help("mot-clé") les guillemets sont obligatoires pour les informations sur un mot-clé (for, while…)

Quelques lettres suivies d'une tabulation affichent toutes les fonctions commençant par ces lettres :

>>> comp # et [tab]
compile(  complex(

Il est possible de produire un fichier texte à partir d'une console :

$ python3 -c "help('while')" > while.txt

Pour un module, par exemple sqlite3 :

python3 -c "import sqlite3 ; help("sqlite3")" > sqlite3.txt

Voir le fichier consacré aux modules.

Documentation sur votre système GNU+Linux

Si Python3 est installé, saisir man python3 dans une console renseigne sur les différentes manières de lancer Python.

Le script /usr/bin/pydoc permet la consultation d'informations sur les fonctions, modules, mots-clés :
pydoc math présente succinctement les fonctions du module math, équivaut à help() plus haut
pydoc divmod présente succinctement la fonction divmod, équivaut à help() plus haut
pydoc keywords liste les mots-clés sur lesquels il y a une information
pydoc -g lance une interface graphique pour une navigation dans le système d'aide

/usr/share/doc/python3 et /usr/share/doc/python3.9 contiennent quelques fichiers d'aide si le paquet python3-doc a été installé (nom du paquet pour Debian)

Le nom des paquets et les adresses peuvent varier selon les distributions et les versions.

Documentation sur Internet