Python (langage)
| Python | ||
| Date de première version | , 35 ans[1] | |
|---|---|---|
| Paradigmes | Objet, impératif et fonctionnel | |
| Auteur | Guido van Rossum | |
| Développeurs | Python Software Foundation | |
| Dernière version | 3.14.7 ()[2] | |
| Version en développement | 3.15.0rc1 ()[3] | |
| Typage | Fort, dynamique, duck typing | |
| Influencé par | ABC, C, Eiffel, ICON, Modula-3, Java, Perl, Smalltalk, Tcl | |
| A influencé | Ruby, Groovy, Boo, Julia, Mojo | |
| Implémentations | CPython, Jython, IronPython, PyPy | |
| Écrit en | C pour CPython, Java pour Jython, C# pour IronPython et en Python lui-même pour PyPy | |
| Système d'exploitation | Multiplateforme | |
| Licence | Licence libre : Python Software Foundation License |
|
| Site web | https://python.org/ | |
| Extensions de fichiers | .py, .pyc, .pyd, .pyo | |
| modifier |
||
Python (prononcé /pi.tɔ̃/) est un langage de programmation interprété, multiparadigme et multiplateformes. Il favorise la programmation impérative structurée, fonctionnelle et orientée objet. Il est doté d'un typage dynamique fort, d'une gestion automatique de la mémoire par ramasse-miettes et d'un système de gestion d'exceptions. Il a des similarités avec Perl, Ruby, Scheme, Smalltalk et Tcl.
Le langage Python est placé sous une licence libre proche de la licence BSD et fonctionne sur la plupart des plateformes informatiques, des smartphones aux ordinateurs centraux, de Microsoft Windows à Unix avec notamment GNU/Linux en passant par macOS, ou encore Android, iOS, et peut aussi être traduit en Java ou .NET. Il est conçu pour optimiser la productivité des programmeurs en offrant des outils de haut niveau et une syntaxe simple à utiliser.
Utilisation
[modifier | modifier le code]Python est un langage de programmation qui peut s'utiliser dans de nombreux contextes grâce à des bibliothèques spécialisées[4].
Il est utilisé comme langage de script pour automatiser des tâches comme la récupération de la météo sur Internet ou l'enchaînement d'actions en conception assistée par ordinateur (voir la section Adoption). On l'utilise également comme langage de développement de prototype lorsqu'on a besoin d'une application fonctionnelle avant de l'optimiser avec un langage compilé. Il est particulièrement répandu dans le monde scientifique, et possède des bibliothèques optimisées pour le calcul numérique[5].
C'est l'un des langages utilisés dans le domaine du big data[6], de l'informatique quantique[7] et de l'intelligence artificielle incluant l'apprentissage automatique[5],[8].
Python à l'école
[modifier | modifier le code]Python est apprécié par les pédagogues qui y trouvent un langage où la syntaxe, clairement séparée des mécanismes de bas niveau, permet une initiation aisée[9] aux concepts de base de la programmation[10].
Cette initiation commence généralement au début du lycée en classe de seconde. Les élèves souhaitant approfondir le sujet peuvent choisir, en classes de première et de terminales, un enseignement de spécialité Numérique et sciences informatiques[11] (NSI).
Les calculatrices supportant Python[11] destinées aux lycéens fonctionnent en Python 3. Ces calculatrices peuvent échanger des programmes avec des ordinateurs personnels.
Chaque année, environ 14 000 lycéens participent à la Nuit du code[12], un challenge à partir de la classe de première NSI pour créer un jeu en 6 heures avec le moteur Pyxel de Python. À Berlin[13] et Tokyo[14], les lycées français internationaux (LFI) participent à l'évènement.
Au LFI de Pékin[15], l'Heure de code est en langage graphique Scratch de puzzles colorés aimantés pour les collégiens ou en langage textuel Python pour les lycéens. Drew Houston[16] (Dropbox), Mark Zuckerberg[16] (Meta), Bill Gates[16] (Microsoft) et Barack Obama[16] apportent leur soutien à Code.org (en), une organisation à but non lucratif à l'initiative de Hour of code[17] et Hour of AI.
En janvier-février, Passe ton hack[18] d'abord réunit 7 000 lycéens en ligne pour capturer le drapeau (en) en programmant en Python[19] la détection d'une injection SQL, d'une attaque par force brute avec dictionnaire d'un mot de passe ou le décryptage d'un chiffrement par décalage de César.
Python est utilisé comme langage de programmation dans l'enseignement secondaire et supérieur, notamment en France[20]. Depuis 2013, il y est enseigné à tous les étudiants de classes préparatoires scientifiques dans le cadre du tronc commun (informatique commune). Auparavant, l'enseignement d'informatique était limité à une option en MP, l'enseignement se faisant en langage Caml ou Pascal[21]. Cette option existe toujours, mais Pascal a été abandonné à partir de la session 2015 des concours et Caml a, lui, été enlevé au profit de OCaml dans cet enseignement. Les premières épreuves de concours portant sur le langage Python sont également celles de la session 2015[22],[23].
Historique
[modifier | modifier le code]Au CWI
[modifier | modifier le code]
En 1982[24], au Centre pour les mathématiques et l'informatique (CWI) d'Amsterdam, aux Pays-Bas, l'informaticien Guido van Rossum participe au développement du langage de programmation ABC conçu pour l'enseignement[25] :PUT "ABC" IN B cible les débutants (Beginners) absolus[24].
Il travaille alors dans l'équipe du système d'exploitation Amoeba dont les appels systèmes sont difficilement interfaçables avec le Bourne shell utilisé comme interface utilisateur. Il estime alors qu'un langage de script inspiré d'ABC[21] pourrait être intéressant comme interpréteur de commandes pour Amoeba[26].
En 1989, profitant d'une semaine de vacances durant les fêtes de Noël, il utilise son ordinateur personnel[27] pour écrire la première version du langage. Fan de la série télévisée Monty Python's Flying Circus, il décide de baptiser ce projet Python[28]. Il s'est principalement inspiré d'ABC, par exemple pour l'indentation comme syntaxe ou les types de haut niveau mais aussi de Modula-3 pour la gestion des exceptions, du langage C et des outils UNIX[29].
Durant l'année suivante, le langage commence à être adopté par l'équipe du projet Amoeba, Guido poursuivant son développement principalement pendant son temps libre. Entre le [30] et le [1], la première version publique, numérotée 0.9.0[31], immédiatement patchée en 0.9.1[32],[30], est postée sur le forum Usenet[26] alt.sources.
La dernière version sortie au CWI est Python 1.2.
Au CNRI
[modifier | modifier le code]En 1995, van Rossum continue son travail sur Python à la Société pour les initiatives nationales de recherche (Corporation for National Research Initiatives ) (en)[33] à Reston, en Virginie, où il sort plusieurs versions du logiciel.
Au CNRI, l'équipe Python travaille sur le navigateur web expérimental Grail[33] utilisant Tcl/Tk. Il est l'équivalent pour Python du navigateur HotJava, permettant d'exécuter des applets dans un environnement sécurisé[34]. Il entraîne le développement de modules pour la bibliothèque standard de gestion de HTML.
En 1999, le projet Computer Programming for Everybody[35] (CP4E) est lancé conjointement entre le CNRI et la DARPA. Il s'agit d'utiliser Python comme un langage d'enseignement de la programmation. Cette initiative conduira à la création de l'environnement de développement dénommé IDLE.
En , Andrew M. Kuchling, le manager pendant une décennie des versions de Python 2.0[36] à 2.7[37], publie une critique dénommée "Les bizarreries de Python" (Python Warts[38]), qui synthétise les griefs les plus fréquents exprimés à l'encontre du langage. Ce document aura une influence certaine sur les développements futurs du langage[39].
Du fait du manque de financement du projet par la DARPA, et du départ de nombreux développeurs Python du CNRI (dont Guido van Rossum), le projet IDLE s'éteint en 2000[35]. Python 1.6 est la dernière version sortie au CNRI.
Zope
[modifier | modifier le code]En 2000, l'équipe principale de développement de Python déménage à BeOpen pour former l'équipe PythonLabs à l’origine de Python 2.0. Après cette version, Guido van Rossum et les autres développeurs de PythonLabs rejoignent Digital Creations à présent connue sous le nom de Zope Corporation[40].
La Python Software Foundation
[modifier | modifier le code]En 2001, Python 2.1 est une version dérivée de Python 1.6.1 et de Python 2.0. Sa licence est renommée Python Software Foundation License. Tout code, documentation et spécification ajouté, depuis la sortie de Python 2.1 alpha, est détenu par la Python Software Foundation (PSF), une association sans but lucratif fondée en 2001, modelée d'après l'Apache Software Foundation.
En 2005, Guido van Rossum travaille sur les projets Mondrian et Rietveld[41].
En 2008, Python 3.0[42] est publié. L'équipe Python a choisi de casser la compatibilité ascendante dans cette nouvelle version majeure pour :
- Réparer certains défauts du langage : par exemple l'orienté objet avec deux types de classes) ;
- Nettoyer la bibliothèque standard de ses éléments obsolètes et redondants.
En 2012, Python 3.1[43] corrige les erreurs de jeunesse de la version 3.0.
Dropbox
[modifier | modifier le code]En 2013, Guido van Rossum est embauché par Dropbox[44] (mypy[45]) jusqu'en 2019[46].
Microsoft
[modifier | modifier le code]En 2020, Guido van Rossum entre dans la division développeur chez Microsoft[8].
Selon l'Index TIOBE, « Python, qui est devenu un élément incontournable de la science des données, du DevOps et du développement web, est aussi désormais le langage le plus populaire dans le classement de TIOBE. Classé troisième langage le plus populaire de l'index au début de l'année 2021, Python s'est hissé à la première place en octobre 2022 »[47], notamment en raison de son efficacité pour l'apprentissage automatique.
En , Python occupe la première place de ce classement[48].
Caractéristiques
[modifier | modifier le code]Syntaxe
[modifier | modifier le code]Python a été conçu pour être un langage lisible. Il vise à être visuellement épuré. Par exemple, il possède moins de constructions syntaxiques que des langages structurés tels que C, Perl, ou Pascal. Les commentaires sont indiqués par le caractère croisillon #[49].
Les blocs sont identifiés par l'indentation[50], au lieu d'accolades comme en C ou C++ ; ou de begin ... end comme en Pascal ou Ruby. Une augmentation de l'indentation marque le début d'un bloc, et une réduction de l'indentation marque la fin du bloc courant. Par convention, l'indentation est de quatre espaces en Python selon le standard de codage PEP 8[51].
| Fonction factorielle en C | Fonction factorielle en Python |
|---|---|
int factorielle(int n) {
if (n < 2) {
return 1;
} else {
return n * factorielle(n - 1);
}
}
|
def factorielle(n):
if n < 2:
return 1
else:
return n * factorielle(n - 1)
|
Remarque : L'indentation pourrait être modifiée ou supprimée dans la version en C sans modifier son comportement. De même, la fonction Python peut être écrite avec une expression conditionnelle[52]. Cependant, une indentation correcte permet de détecter plus aisément des erreurs en cas d'imbrication de plusieurs blocs et facilite donc l'élimination de ces erreurs. C'est pourquoi il est préférable d'indenter convenablement les programmes en C. La version courte s'écrirait ainsi :
| Fonction factorielle en C | Fonction factorielle en Python |
|---|---|
int factorielle(int n)
{ // appel récursif
return n < 2 ? 1 : n * factorielle(n-1);
}
|
def factorielle(n): # appel récursif
return 1 if n < 2 else n * factorielle(n-1)
|
Mots-clés du langage
[modifier | modifier le code]Les mots-clés réservés du langage Python sont fournis dans la liste keyword.kwlist du module keyword[53].
Les mots-clés de Python 2.7.5 sont les suivants : and, as, assert, break, class, continue, def, del, elif, else, except, exec, finally, for, from, global, if, import, in, is, lambda, not, or, pass, print, raise, return, try, while, with, yield.
À partir de Python 3.0, print et exec ne sont plus des mots-clés du langage, mais des fonctions du module builtins[54]. Sont ajoutés aux mots-clés : True, False, None et nonlocal. Les trois premiers étaient déjà présents dans les versions précédentes, mais ils ne sont plus modifiables (auparavant, l'affectation True = 1 était possible)[55]. nonlocal a été introduit par le PEP 3104[56], et permet, dans une fonction définie à l'intérieur d'une autre fonction, de modifier une variable d'un niveau supérieur de portée. Avant cela, seules les variables locales à la fonction, et globales (niveau module) étaient modifiables. Toutefois, il était possible, et ça l'est toujours sans le mot-clé nonlocal, de modifier un objet affecté à une variable d'un niveau de portée supérieur, par exemple une liste avec la méthode append - c'est évidemment impossible pour un objet immuable.
À partir de Python 3.10, il y a 3 mots-clés contextuels (« soft keywords » en anglais) : match, case, _ identique à l’instruction switch-case.
match valeur:
case condition_1:
expression_1
case condition_2:
expression_2
case _: # `case _´ est accédé si toutes les autres conditions sont fausses.
expression_par_défaut
Types de base
[modifier | modifier le code]Les types de base en Python sont relativement complets et puissants. Il y a, entre autres :
Les objets numériques :
intest le type des entiers relatifs. Avant la version 3.0, ce type était dénommélong, et le typeintcorrespondait à un entier de 32 ou 64 bits. Néanmoins, une conversion automatique en typelongévitait tout débordement. Maintenant, ce type correspond aux entiers relatifs avec une précision illimitée sans restriction de taille.longest le type des entiers relatifs, illimités de plus de 32 bits en Python 2, remplacé par le typeinten Python 3.floatest le type flottant équivalent au typedoubledu C, soit tout nombre entre −1,7 × 10308 et 1,7 × 10308 sur les plateformes conforme à l'IEEE 754.complexest le type des approximations des nombres complexes (c'est-à-dire deuxfloat).
Les objets itérables sont parcourus à l'aide d'une boucle for de la manière suivante :
for element in objet_iterable:
traiter(element)
bytearrayest une chaîne d'octets modifiables. La version d'Unicode employée par Python peut être déterminée à l'aide de la variableunidata_versiondu moduleunicodedata.dictest un dictionnaire ou tableau associatif pour associer chaque clef unique à un objet. Ses méthodes sont.keys(),.values()ou.items().enumerate()énumère un objet itérable tel qu'une liste. Par rapport à la bouclefor, il renvoie à la fois l'index[57] et la valeur. L'objet énuméré n'est pas modifiable : il est dit immuable.filecorrespond à un fichier obtenu grâce à la méthodewith open('c:\tool\python\pep-343.html', 'r') as file:frozensetforme une variante immuable d'unset.listest un tableau dynamique qui étend automatiquement sa taille lorsque nécessaire et accepte des types de données hétérogènes.range(nbr)est un compteur. Il génère une séquence de nombres de 0 à nbr - 1.setest un ensemble non ordonné d'objets.strest une chaîne de caractères itérable caractère par caractère. À partir de la version 3.0, les caractères sont en Unicode sur 16 ou 32 bits ; les chaînes d'octets sont des objetsbytes[58],[59]. Dans les versions précédentes, ces objets étaient respectivement de typeUnicodeetstr. Les objetsstretbytessont immuables.tuple(n-uplet) est une liste immuable d'objets de types pouvant être différents c'est-à-dire hétérogènes.typenameest obtenu avec la fonctionnamedtuple(). C'est une variante destuplepermettant d'accéder à un élément du tuple avec un nom se comportant comme une variable. Contrairement auxdict, ces objets sont immuables[60],[61].
Les autres objets ne sont ni numériques ni itérables :
boolest un booléen, soit le type deTrueetFalserenvoyés par exemple lors de comparaisons hors de l'utilisation de méthodesis_x().exceptionest le type d'un message d'erreur lancé lorsque le code lève une exception.functionest le type d'une fonction, utilisé lors de l'appel des mots-clefdefetlambda.moduleest le type d'un module, utilisé lors de l'appel des mots-clefimportetfrom.Nonesert à dénoter qu'une variable est vide.NotImplementedTypeindique une absence d'implémentation du type auquel on essaie d'accéder.objectest le type basique dont tous les autres types « héritent ».sliceest une partie de type ou un objet extensible.typeest le type du type des objets, obtenu grâce à la méthodetype().
Il est possible de dériver les classes des types de base pour créer ses propres types. On peut également fabriquer ses propres types d'objets itérables sans hériter des itérables de base en utilisant le protocole d'itération du langage.
Programmation fonctionnelle
[modifier | modifier le code]Python permet de programmer dans un style fonctionnel. Il dispose également des compréhensions de listes. Plus généralement, les compréhensions peuvent produire des générateurs, des dictionnaires ou des ensembles[62],[63].
Exemple : pour construire la liste des carrés des entiers naturels plus petits que 10, on peut utiliser l'expression :
liste = [x**2 for x in range(10)]
# liste = [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
La liste des nombres pairs :
liste = [entier for entier in range(10) if entier % 2 == 0]
# liste = [0, 2, 4, 6, 8]
Une table de passage des lettres de l'alphabet vers leur code ASCII :
{chr(n): n for n in range(65, 91)}
# {'A': 65, 'B': 66, 'C': 67, ..., 'X': 88, 'Y': 89, 'Z': 90}
L'ensemble des lettres du mot "abracadabra" (produit l'ensemble {'a', 'b', 'r', 'c', 'd'}) :
s = "abracadabra"
{c for c in s}
Une compréhension peut comprendre plusieurs boucles et filtres, et il existe une correspondance avec le code réalisant le même calcul à l'aide d'instructions for et if :
| Compréhension | Code équivalent |
|---|---|
n = 6
[ i + j if i != j else 0
for i in range(n) # sans ":"
if i % 2 != 0 # impaire ?
for j in range(n)
if j % 3 != 0 ]
# [0, 3, 5, 6, 4, 5, 7, 8, 6, 7, 9, 0]
|
n = 6; lstRes = [] # La liste résultat est vide
for i in range(n): # avec ":"
if i % 2 != 0: # impaire ?
for j in range(n):
if j % 3 != 0:
lstRes.append(i + j if i != j else 0)
# lstRes = [0, 3, 5, 6, 4, 5, 7, 8, 6, 7, 9, 0]
|
Cependant, une différence notable dans la version sans compréhension est que les variables i et j existent, avec la valeur qu'elles avaient lors de leur dernier tour de boucle. Ce n'est pas le cas pour des constructions par compréhension.
Une forme limitée de fonction anonyme est possible :
lambda x: x + 2
Les fonctions lambda peuvent être définies en ligne et utilisées comme arguments dans des expressions fonctionnelles :
list(filter(lambda x: x % 2 == 0, range(10)))
# renvoie [0, 2, 4, 6, 8]
retournera une liste constituée des nombres pairs inférieurs à 10.
Le même résultat peut être obtenu avec :
[x for x in range(10) if x % 2 == 0]
# renvoie [0, 2, 4, 6, 8]
Les lambdas de Python n'admettent que des expressions et ne peuvent être utilisées comme fonctions anonymes généralisées ; mais en Python, toutes les fonctions sont des objets, elles peuvent donc être passées en arguments à d'autres fonctions, et appelées lorsque c'est nécessaire. En effet, une fonction définie avec def peut être créée à l'intérieur d'une autre fonction et on obtient ainsi une définition de fonction dans une variable locale, par exemple :
def filtre_inferieur_a_5(une_liste):
def mon_filtre(x): # variable locale mon_filtre
return x < 5
return filter(mon_filtre, une_liste)
Une fonction locale peut modifier l'environnement de la fonction qui l'a créée, grâce au mot-clé nonlocal (voir Fermeture (informatique)) :
from typing import Callable # type le retour de fonction
def accum(pas) -> Callable[[int], int]: # retourne une fonction appelable
total = 0 # initialise une fois l'accumulateur
def ajoute(germe) -> int:
nonlocal total # accède à l'accumulateur de la fonction accum
total += germe * pas # incrémente l'accumulateur du germe fois le pas
return total # retourne la valeur accumulée
return ajoute # retourne la fonction accumulateur paramétrée par le pas
paire = accum(2) # retourne la fonction ajoute avec un pas de 2
assert isinstance(paire, Callable) # paire est une fonction appelable
print([cell.cell_contents for cell in paire.__closure__]) # environnement initial : [2, 0]
print ([paire(1) for _ in range(5)]) # affiche la liste des cinq premiers nombres pairs
# [2, 4, 6, 8, 10]
print ([paire(1) for _ in range(3)]) # affiche la suite à partir du dernier compteur précédent
# [12, 14, 16]
print([cell.cell_contents for cell in paire.__closure__]) # environnement final : [2, 16]
On peut ainsi créer plusieurs accumulateurs, faisant chacun référence à son propre total. Il est possible d'accéder à l'environnement d'une fonction locale à l'aide de l'attribut __closure__.
Programmation objet
[modifier | modifier le code]Tous les types de base, les fonctions, les instances de classes (les objets « classiques » des langages C++ et Java) et les classes elles-mêmes (qui sont des instances de méta-classes) sont des objets.
Une classe se définit avec le mot-clé class. Les classes Python supportent l'héritage multiple ; il n'y a pas de surcharge statique comme en C++, ou de restrictions sur l'héritage comme c'est le cas en Java (une classe implémente plusieurs interfaces et hérite d'une seule classe) mais le mécanisme des arguments optionnels et par mot-clé est plus général et plus flexible. En Python, l'attribut d'un objet peut référencer une variable d'instance ou de classe (le plus souvent une méthode). Il est possible de lire ou de modifier un attribut dynamiquement avec les fonctions :
getattr(objet, "nom_attribut")setattr(objet, "nom_attribut", nouvel_attribut)
Exemple de deux classes simples :
class Personne:
def __init__(self, nom, prenom):
self.nom = nom
self.prenom = prenom
def presenter(self):
return self.nom + " " + self.prenom
class Etudiant(Personne):
def __init__(self, niveau, nom, prenom):
Personne.__init__(self, nom, prenom)
self.niveau = niveau
def presenter(self):
return self.niveau + " " + Personne.presenter(self)
e = Etudiant("Licence INFO", "Dupontel", "Albert")
assert e.nom == "Dupontel"
Méthodes spéciales et définition des opérateurs
[modifier | modifier le code]Python fournit un mécanisme élégant et orienté objet pour définir un ensemble prédéfini d'opérateurs : tout objet Python peut se voir doté de méthodes dites spéciales.
Ces méthodes, commençant et finissant par deux tirets de soulignement (underscores), sont appelées lors de l'utilisation d'un opérateur sur l'objet : + (méthode __add__), += (méthode __iadd__), [] (méthode __getitem__), () (méthode __call__), etc. Des méthodes comme __repr__ et __str__ permettent de définir la représentation d'un objet dans l'interpréteur interactif et son rendu avec la fonction print.
Les possibilités sont nombreuses et sont décrites dans la documentation du langage[64].
Par exemple on peut définir l'addition de deux vecteurs à deux dimensions avec la classe suivante :
class Vector2D:
def __init__(self, x, y):
# On utilise un tuple pour stocker les coordonnées
self.coords = (x, y)
def __add__(self, other):
# L'instruction a+b sera résolue comme a.__add__(b)
# On construit un objet Vector2D à partir des coordonnées propres à l'objet, et à l'autre opérande
return Vector2D(self.coords[0]+other.coords[0], self.coords[1]+other.coords[1])
def __repr__(self):
# L'affichage de l'objet dans l'interpréteur
return "Vector2D(%s, %s)" %self.coords
a = Vector2D(1, 2)
b = Vector2D(3, 4)
print(a + b) # Vector2D(4, 6)
Générateurs
[modifier | modifier le code]Le mot-clef yield utilisé dans une fonction permet de faire de cette fonction un générateur. L'appel de cette fonction renvoie un objet de type generator, qui peut être utilisé dans une boucle for, par exemple.
À chaque appel, le générateur effectue son traitement jusqu'à rencontrer le mot-clé yield, renvoie la valeur de l'expression yield, et à l'appel suivant, reprend son déroulement juste après le yield. Par exemple pour calculer la suite de Fibonacci, on peut écrire :
def gen_fibonacci():
"""Générateur de la suite de Fibonacci"""
a, b = 0, 1
while True:
yield a # Renvoie la valeur de "a", résultat de l'itération en cours
a, b = b, a + b
fi = gen_fibonacci()
print([next(fi) for _ in range(7)])
# renvoie [0, 1, 1, 2, 3, 5, 8]
print([next(fi) for _ in range(3)])
# renvoie [13, 21, 34]
Le module itertools permet de manipuler les générateurs. Par exemple, pour extraire les 10 premiers éléments du générateur précédent :
import itertools
list(itertools.islice(gen_fibonacci(), 10))
# renvoie [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Depuis Python 3.3, il est possible de produire un générateur à partir d'une fonction récursive, grâce à la syntaxe yield from, apparue dans le PEP 380[65] et qui « délègue » le calcul à un sous-générateur. L'exemple suivant calcule les permutations des dames correspondant aux solutions du problème des huit dames étendu à un échiquier de taille n × n.
def QueenSolver(nbrFile, lstColumn=[]):
'''Résoudre nbrFile Dames sans prise sur un échiquier de nbrFile colonnes'''
if (nbrRank := len(lstColumn)) == nbrFile:
yield lstColumn # Solution itérable trouvée
else:
for indFile in [col for col in range(1,nbrFile+1) if col not in lstColumn]:
isQueenUnderAttack = False; indRank = nbrRank
for col in lstColumn:
if col in [indFile+indRank,indFile-indRank]: # Collision ?
isQueenUnderAttack = True; break # colonne col à rejeter
indRank -= 1 # Rangée précédente
if not(isQueenUnderAttack): # Dame non attaquée ?
# appel récursif en insérant dans la liste la Dame en indFile
yield from QueenSolver(nbrFile, lstColumn + [indFile])
sum(1 for _ in QueenSolver(8)) # Nombre de solutions
# renvoie 92
Un générateur peut sembler identique à une fonction qui retourne une liste par return, mais contrairement à une liste qui contient tous ses éléments, un générateur calcule ses éléments un par un.
import timeit # chronomètre
[n * n for n in range(10)] # une liste est entre crochets
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
36 in [n * n for n in range(10)] # 36 est-il dans la liste des carrés ?
# True
(n * n for n in range(10)) # un générateur est entre parenthèses
# <generator object <genexpr> at 0x0000022DCAED1490> # l'adresse hexadécimale peut changer
36 in (n * n for n in range(10)) # 36 est-il dans un des premiers résultats du générateur ?
# True
timeit.timeit(stmt='36 in [n * n for n in range(100)]', number=1_000_000) # quand range(maxNbr) augmente,
# 7.3 s
timeit.timeit(stmt='36 in (n * n for n in range(100))', number=1_000_000) # le générateur peut être plus rapide.
# 1.2 s
Ainsi, le test 36 in [n * n for n in range(10)] va s'effectuer sur la liste calculée en entier, alors que dans 36 in (n * n for n in range(10)), qui utilise un générateur, le calcul des carrés s'arrête dès que 36 est trouvé. On peut s'en convaincre en remplaçant n * n par un appel de fonction réalisant un effet de bord, par exemple un affichage à l'écran.
Réflexivité
[modifier | modifier le code]Grâce à un usage intensif des dictionnaires (conteneur associatif développé avec des tables de hachage), Python permet d'explorer les divers objets du langage (introspection) et dans certains cas de les modifier (intercession).
Typage
[modifier | modifier le code]
Le typage est dynamique[66]. Il n'est pas vérifié à la compilation mais à l'exécution. Il n'est pas nécessaire d'indiquer le type des variables : Python est sans typage statique explicite.
Python est fortement typé. Il interdit à l'exécution des opérations ayant peu de sens.
Par exemple : concaténer par l'opérateur + un nombre réel ou entier à une chaîne str pour l'afficher avec print().
Il n'y a pas de conversion automatique.
Python propose les fonctions int() et str() permettant de convertir un nombre dans un autre type :
floatPoint = 3.2 # Python découvre dynamiquement que floatPoint est du type float
print("Tu as " + floatPoint + " points !") # Génère l'erreur de typage :
# TypeError: can only concatenate str (not "float") to str
# intPoint est du type int : entier. La fonction int() force la conversion.
intPoint = int(floatPoint) # Sa valeur 3 est arrondie à l'unité inférieure.
print("Tu as " + intPoint + " points !")
# TypeError: can only concatenate str (not "int") to str
strPoint = str(intPoint) # strPoint est du type str : chaîne de caractères
print("Tu as " + strPoint + " points !") # affiche "Tu as 3 points !"'
En pratique, il n'est pas utile de préfixer les noms de variables par leur type.
La conversion d'un nombre vers str est automatique avec une chaîne préfixée par f en mettant la variable entre accolades à l'intérieur de la chaîne sans opérateur + :
nbrPoint = 3.2 # Python reconnaît dynamiquement que nbrPoint est du type float
print(f"Tu as {nbrPoint} points.") # affiche "Tu as 3.2 points."
print(f"Tu as {int(nbrPoint)} points.") # affiche "Tu as 3 points."
print(f"Tu as {nbrPoint:.0f} points.") # affiche "Tu as 3 points." avec zero décimale
Python utilise le typage dynamique dénommé duck typing : lors de l'exécution, si une méthode invoquée sur un objet a la même signature qu'une méthode déclarée sur cet objet, alors c'est cette dernière méthode qui est exécutée. De ce fait, invoquer une méthode qui n'existe pas sur un objet va échouer, signifiant que l'objet en question n'est pas du bon type.
Python propose aussi un mécanisme de typage statique pour les attributs des classes grâce à l'API trait[67] ou au patron de conception decorators.
Annotations
[modifier | modifier le code]Depuis la version 3.0, Python propose l'annotation des variables dans les fonctions (introduit dans la PEP 3107[68]). Ce qui permet de rendre le code plus lisible sans pour autant faire office de solution de typage statique puisque rien n'oblige à suivre ces annotations[69].
def hello(name: str) -> str:
return "Hello {} !".format(name)
hello("Alice") # Appel suggéré par les annotations
hello(True) # Appel non conforme mais tout à fait fonctionnel
En complément, depuis la version 3.5, Python propose le module typing[70] (introduit dans la PEP 484[71]).
from typing import List
def split_string(string: str) -> List[str]:
return string.split(" ")
Analyse statique
[modifier | modifier le code]Il est possible d'effectuer une analyse statique des modules Python avec des outils comme Pylance[72], Pylint[73], mypy[45], ou PyChecker. Sans nécessiter une exécution, ces outils repèrent des fautes ou des constructions déconseillées. Par exemple, une classe qui hérite d'une classe abstraite et qui ne redéfinit pas les méthodes abstraites, ou bien des variables utilisées avant d'être déclarées, ou encore des attributs d'instance déclarés en dehors de la méthode __init__.
Désassembleur
[modifier | modifier le code]Il est possible de désassembler le code intermédiaire (bytecode) produit par CPython, l'implémentation de référence de Python, à l'aide du module dis[74] :
import dis
dis.dis("val = 0; val += 1")
Les instructions sont :
0 RESUME 0
1 LOAD_CONST 0 (0)
STORE_NAME 0 (val)
LOAD_NAME 0 (val)
LOAD_CONST 1 (1)
BINARY_OP 13 (+=)
STORE_NAME 0 (val)
RETURN_CONST 2 (None)
Modèle objet
[modifier | modifier le code]En Python, tout est objet[75], dans le sens qu'une variable peut contenir une référence vers tous les éléments manipulés par le langage : nombres, méthodes, modules, etc.. Néanmoins, avant la version 2.2, les classes et les instances de classes étaient un type d'objet particulier, ce qui signifiait qu'il était par exemple impossible de dériver sa propre sous-classe de l'objet list.
Méthodes
[modifier | modifier le code]Le modèle objet de Python est inspiré de celui de Modula-3[29]. Parmi ces emprunts se trouve l'obligation de déclarer l'instance de l'objet courant, conventionnellement nommée self, comme premier argument des méthodes, et à chaque fois que l'on souhaite accéder à une donnée de cette instance dans le corps de cette méthode. Cette pratique n'est pas naturelle pour des programmeurs venant par exemple de C++ ou Java, la profusion des self étant souvent critiquée comme étant une pollution visuelle qui gêne la lecture du code. Les promoteurs du self explicite estiment au contraire qu'il évite le recours à des conventions de nommage pour les données membres et qu'il simplifie des tâches comme l'appel à une méthode de la superclasse ou la résolution d'homonymie entre données membres[76].
Python reconnaît trois types de méthodes :
- les méthodes d'instance, qui sont celles définies par défaut. Elles reçoivent comme premier argument une instance de la classe où elles ont été définies.
- les méthodes de classe, qui reçoivent comme premier argument la classe où elles ont été définies. Elles peuvent être appelées depuis une instance ou directement depuis la classe. Elles permettent de définir des constructeurs alternatifs comme la méthode
fromkeys()de l'objetdict. Elles sont déclarées avec le décorateur@classmethod. - les méthodes statiques, qui ne reçoivent pas de premier argument implicite. Elles sont déclarées avec le décorateur
@staticmethod.
Visibilité
[modifier | modifier le code]Le langage a un support très limité de l'encapsulation. Il n'y a pas, comme en Java par exemple, de contrôle de l'accessibilité par des mots clefs comme protected ou private.
La philosophie de Python est de différencier conceptuellement l'encapsulation du masquage d'information. Le masquage d'information vise à prévenir les utilisations frauduleuses, c'est une préoccupation de sécurité informatique. Le module bastion de la bibliothèque standard, qui n'est plus maintenu dans les dernières versions du langage, permettait ainsi de contrôler l'accès aux attributs d'un objet dans le cadre d'un environnement d'exécution restreint.
L'encapsulation est une problématique de développement logiciel. Le slogan des développeurs Python est we're all consenting adults here[77] (nous sommes entre adultes consentants). Ils estiment en effet qu'il suffit d'indiquer, par des conventions d'écriture, les parties publiques des interfaces et que c'est aux utilisateurs des objets de se conformer à ces conventions ou de prendre leurs responsabilités. L'usage est de préfixer par un underscore les membres privés. Le langage permet par ailleurs d'utiliser un double underscore pour éviter les collisions de noms, en préfixant automatiquement le nom de la donnée par celui de la classe où elle est définie.
L'utilisation de la fonction property() permet de définir des propriétés qui ont pour but d'intercepter, à l'aide de méthodes, les accès à une donnée membre. Cela rend inutile la définition systématique d'accesseurs et le masquage des données comme il est courant de le faire en C++ par exemple.
Héritage
[modifier | modifier le code]Python supporte l'héritage multiple. Depuis la version 2.3, il utilise l'algorithme C3, issu du langage Dylan[78], pour résoudre l'ordre de résolution de méthode (MRO). Les versions précédentes utilisaient un algorithme de parcours en profondeur qui posait des problèmes dans le cas d'un héritage en diamant[79].
Bibliothèque standard
[modifier | modifier le code]
Python possède une grande bibliothèque standard, fournissant des outils convenant à de nombreuses tâches diverses. Le nombre de modules de la bibliothèque standard peut être augmenté avec des modules spécifiques écrits en C ou en Python.
La bibliothèque standard est particulièrement bien conçue pour écrire des applications utilisant Internet, avec un grand nombre de formats et de protocoles standards gérés (tels que MIME et HTTP). Des modules pour créer des interfaces graphiques et manipuler des expressions rationnelles sont également fournis. Python inclut également un framework de tests unitaires (unittest, anciennement PyUnit avant version 2.1) pour créer des suites de tests exhaustives.
Conventions de style
[modifier | modifier le code]Bien que chaque programmeur puisse adopter ses propres conventions pour l'écriture de code Python, Guido van Rossum a mis un guide à disposition, référencé comme PEP 8[51],[73]. Publié en 2001, il est toujours maintenu pour l'adapter aux évolutions du langage. Google propose également un guide[80].
Interfaces graphiques
[modifier | modifier le code]
Python possède plusieurs modules disponibles pour la création de logiciels avec une interface graphique. Le plus répandu est Tkinter[81]. Ce module convient à beaucoup d'applications et peut être considéré comme suffisant dans la plupart des cas. Néanmoins, d'autres modules ont été créés pour pouvoir lier Python à d'autres bibliothèques logicielles (« toolkit »), pour davantage de fonctionnalités, pour une meilleure intégration avec le système d'exploitation utilisé, ou simplement pour pouvoir utiliser Python avec sa bibliothèque préférée. En effet, certains programmeurs trouvent l'utilisation de Tkinter plus pénible que d'autres bibliothèques. Ces autres modules ne font pas partie de la bibliothèque standard et doivent donc être obtenus séparément.
Les principaux modules donnant accès aux bibliothèques d'interface graphique sont Tkinter pour Tk, wxPython pour wxWidgets, PyGTK pour GTK, ainsi que PyQt et PySide pour Qt. Il existe aussi une adaptation de la bibliothèque SDL : Pygame, un binding de la SFML : PySFML, ainsi qu'une bibliothèque écrite spécialement pour Python : Pyglet.
Il est aussi possible de créer des applications Silverlight en Python sur la plateforme IronPython.
La communauté Python
[modifier | modifier le code]Guido van Rossum est le principal auteur de Python, un langage de programmation largement utilisé dans divers domaines, allant du développement web à l'intelligence artificielle. Son rôle central dans l'évolution de Python lui a valu le titre humoristique de « Dictateur bienveillant à vie » (Benevolent Dictator for Life, BDFL[82]) « par intérim[25] ». Cependant, en , Guido van Rossum a annoncé sa retraite de ce rôle, se déclarant en « vacances permanentes » de ses responsabilités de BDFL[83]. Par la suite, en , il a également retiré sa candidature au conseil directeur du langage Python[84].
Après le retrait de van Rossum, la gouvernance de Python est passée à un modèle plus démocratique, sous la direction d'un Conseil directeur composé de cinq membres élus. Ces membres sont principalement issus de la communauté des core developers, une équipe de développeurs ayant un accès en écriture au dépôt de CPython, l'implémentation de référence du langage Python. Cette équipe se coordonne principalement via la liste de diffusion python-dev, où sont discutées et décidées les évolutions du langage et de sa bibliothèque standard.
Les contributions de la communauté sont encouragées, et les développeurs tiers peuvent soumettre des améliorations via la plateforme de gestion de bugs et de suivi de tâches Roundup, qui a remplacé l'ancien système basé sur SourceForge. La transition vers GitHub en 2017 a également facilité la collaboration ouverte et la contribution au code source de Python.
Les utilisateurs et développeurs de bibliothèques tierces peuvent échanger via diverses autres ressources en ligne, notamment le forum Usenet anglophone comp.lang.python, ainsi que des forums, mailing lists, et réseaux sociaux plus modernes comme Reddit ou Discord.
Les références aux Monty Python[28], une troupe comique britannique, sont un élément récurrent dans la culture Python[85]. Illustrant l'humour décalé[86] et omniprésent dans la communauté Python, la documentation du langage utilise souvent les termes spam et eggs comme espace réservé, en référence au célèbre sketch Spam des Monty Python, où le SPAM (un jambon en conserve) est le leitmotiv du menu truffé d'expressions en français. Ce sketch a d'ailleurs donné son nom au phénomène du courriel non sollicité[87].
Les résultats peuvent différer par rapport à la documentation officielle de Python[88] :
Command-line example
Here are some examples of the random command-line interface:
PS C:\Tool\python> # Choose one at random
PS C:\Tool\python> python -m random egg bacon sausage spam "Lobster Thermidor aux crevettes with a Mornay sauce"
spam
PS C:\Tool\python> python -m random egg bacon sausage spam "Lobster Thermidor aux crevettes with a Mornay sauce"
egg
PS C:\Tool\python> # With explicit arguments
PS C:\Tool\python> python -m random --choice egg bacon sausage spam "Lobster Thermidor aux crevettes with a Mornay sauce"
Lobster Thermidor aux crevettes with a Mornay sauce
Adoption de Python
[modifier | modifier le code]Plusieurs entreprises ou organismes mentionnent sur leur site officiel[89] qu'elles utilisent Python :
- Google utilise Python comme langage principal parmi les langages dynamiques[80]. Guido van Rossum a travaillé au sein de cette entreprise entre 2005 et 2012[90] ;
- Microsoft : depuis 2020, Guido van Rossum a rejoint cette entreprise[8] ;
- Industrial Light & Magic ;
- Instagram[91] ;
- la NASA[92],[93] ;
- et CCP Games, les créateurs du jeu vidéo EVE Online.
Python est aussi le langage de commande d'un grand nombre de logiciels libres :
- FreeCAD, logiciel de CAO 3D
- Blender, logiciel de modélisation 3D et d'édition vidéo
- Inkscape, logiciel de dessin vectoriel
- LibreOffice et Apache OpenOffice, les deux branches de développement d'une suite bureautique issue de StarOffice
- Portage (en), le gestionnaire de paquets du système d'exploitation Gentoo
- ParaView, logiciel de visualisation de données numériques
- Kodi, un lecteur multimédia
- QGIS, un logiciel de cartographie
- Weblate, un outil de traduction
- gedit, un éditeur de texte (les plugins sont écrits en Python)
- SageMath, un logiciel de calcul formel
Et commerciaux :
- Wing IDE, environnement de développement intégré spécialisé sur Python, et écrit en Python
- Corel Paint Shop Pro, logiciel de traitement d'image et d'édition graphique
- capella, logiciel de notation musicale
- ArcGIS[94], un logiciel de cartographie
Implémentations du langage
[modifier | modifier le code]Outre la version de référence, nommée CPython (car écrite en langage C), il existe d'autres systèmes mettant en œuvre le langage Python[95] :
- Stackless Python, une version de CPython n'utilisant pas la pile d'appel du langage C (projet abandonné en 2025) ;
- Jython, un interprète Python pour machine virtuelle Java. Il a accès aux bibliothèques fournies avec l'environnement de développement Java ;
- IronPython, un interprète / compilateur (expérimental) pour plateforme .Net / Mono ;
- Brython[96], une implémentation de Python 3 pour les navigateurs web ;
- MicroPython, variante légère pour microcontrôleurs ;
- PyPy un interprète Python écrit dans un sous-ensemble de Python compilable vers le C ou LLVM ;
- un compilateur (expérimental) pour Parrot, la machine virtuelle de Perl 6 ;
- Shed Skin[97], un compilateur d'un sous-ensemble de Python produisant du code en C++ ;
- Unladen Swallow (en)[98], une version de CPython optimisée et basée sur LLVM archivée en ;
- RustPython est un interpréteur Python 3 en Rust[99].
Ces autres versions ne bénéficient pas forcément de la totalité de la bibliothèque de fonctions écrites en C pour la version de référence, ni des dernières évolutions du langage.
Distributions
[modifier | modifier le code]Différentes distributions sont disponibles, qui incluent des paquets dédiés à un domaine donné :
- La version officielle[100],[101] de la fondation logicielle Python.
- ActiveState Python[75] : distribution commerciale de Python
- Anaconda ou Miniconda[102] optimisée en taille : distribution à usage scientifique, disponible en version gratuite ou commerciale.
- Intel Distribution for Python : distribution installable par conda ou pip, intégrant la bibliothèque oneMKL (en) d'Intel afin d'accélérer les calculs numériques[92] de NumPy et SciPy[103].
- Pyzo : distribution scientifique destinée à être facile d'utilisation[104],[105].
- WinPython[106] : distribution à usage scientifique avec l'éditeur Spyder.
Ce ne sont pas des implémentations différentes du langage Python : elles sont basées sur la référence CPython, mais sont livrées avec plus ou moins de bibliothèques préinstallées. Ces modules tiers[8] peuvent être en versions différentes d'une distribution à l'autre, introduire des contraintes de dépendance ou avoir des cycles de développement propres qui peuvent ne pas être synchronisés avec la dernière version officielle.
Développement
[modifier | modifier le code]Les PEP
[modifier | modifier le code]Les propositions d'amélioration de Python (ou PEP : Python Enhancement Proposal) sont des documents textuels qui ont pour objet d'être la voie d'amélioration de Python et de précéder toutes ses modifications[107]. Un PEP est une proposition d'orientation pour le développement (process PEP), une proposition technique (Standard Track PEP) ou une simple recommandation (Informational PEP). La PEP la plus connue est la PEP 8[51] pour son guide sur le style de code.
Historique des versions
[modifier | modifier le code]
L'historique présente un extrait des nouveautés majeures du logiciel Python par version avec la date de début de sortie et celle de fin de support. Les mises à jour de sécurité sont assurées jusqu'à la date entre parenthèses.
Chaque nouveauté correspond à une proposition d'amélioration de Python (PEP) acceptée dont le numéro apparaît en dernière colonne. Ce tableau n'est pas exhaustif. Se reporter, en première colonne, à chaque version pour l'ensemble des liens des PEP avec leurs auteurs.