Python (langage) - Définition

Source: Wikipédia sous licence CC-BY-SA 3.0.
La liste des auteurs de cet article est disponible ici.

Introduction

Python
Python.svg

Apparu en 1990
Auteur Guido van Rossum
Développeurs Python Software Foundation
Dernière version 3.1.2 [+/−]
Version en développement [+/−]
Paradigmes Objet, impératif
Typage Fort, dynamique
Influencé par ABC, C, ICON, Modula-3, Perl, Smalltalk, Tcl
A influencé Ruby, Groovy, Boo
Implémentations CPython, Jython, IronPython, PyPy
Système d'exploitation Multiplate-forme
Licence Python Software Foundation License
Site Web www.python.org

Python est un langage de programmation interprété multi-paradigme. Il favorise la programmation impérative structurée, 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 est ainsi similaire à 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 plates-formes informatiques, des supercalculateurs aux ordinateurs centraux, de Windows à Unix en passant par Linux et MacOS, avec Java ou encore .NET. Il est conçu pour optimiser la productivité des programmeurs en offrant des outils de haut niveau et une syntaxe simple à utiliser. Il est également 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 plus aisée aux concepts de base de la programmation.

Utilisations

Python est un langage qui peut s'utiliser dans de nombreux contextes et s'adapter à tout type d'utilisation grâce à des bibliothèques spécialisées à chaque traitement. Il est cependant particulièrement utilisé comme langage de script pour automatiser des tâches simples mais fastidieuses comme par exemple un script qui récupérerait la météo sur internet ou qui s'intégrerait dans un logiciel de conception assistée par ordinateur afin d'automatiser certains enchaînements d'actions répétitives. 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 de plus bas niveau. Il est particulièrement répandu dans le monde scientifique, et possède de nombreuses extensions destinées aux applications numériques.

Caractéristiques

Syntaxe

Python a été conçu pour être un langage lisible. Il vise à être visuellement épuré, et utilise des mots anglais fréquemment là où d'autres langages utilisent de la ponctuation, et possède également moins de constructions syntaxiques que de nombreux langages structurés tels que C, Perl, ou Pascal. Les commentaires sont indiqués par le caractère dièse.

Les blocs sont identifiés par l'indentation, au lieu d'accolades comme en C/C++, ou de Begin ... End comme en Pascal. 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. Les parenthèses sont facultatives dans les structures de contrôle :

Fonction factorielle en C Fonction factorielle en Python
       // Fonction factorielle en C       int factorielle(int x)        {                 if (x == 0)                                   return 1;                              else               return x * factorielle(x-1);       }      
       # Fonction factorielle en python       def factorielle(x):           if x == 0:               return 1           else:               return x * factorielle(x-1)      

Types de base

Les types de base en Python sont relativement complets et puissants, il y a entre autres :

  • Les objets numériques
    • int est un entier illimité. Avant la version 3.0, ce type était dénommé long, et le type int correspondait à un entier 32 ou 64 bits. Néanmoins, une conversion automatique évitait tout débordement.
    • float est un flottant équivalent au type double du C, soit un nombre entre -1,7×10308 et 1,7×10308
    • complex est une approximation d'un nombre complexe (typiquement deux floats)
  • Les objets "itérables"
    • Les objets tuple (ou n-uplet) sont des listes non mutables d'objets hétérogènes.
    • Les objets list sont des tableaux dynamiques (ils étendent automatiquement leur taille lorsque nécessaire) et acceptent des types de données hétérogènes.
    • Les objets set sont des ensembles non ordonnés d'objets.
    • Les objets (frozenset) forment une variante non mutable des set.
    • Les objets dict sont des tableaux associatifs (ou dictionnaires) permettant d'associer un objet (une clef) à un autre.
    • Les objets str sont des chaînes de caractères. À partir de la version 3.0, les caractères sont encodés Unicode sur 16 ou 32 bits ; les chaines d'octets ASCII sont des objets bytes. Dans les versions précédentes, ces objets étaient respectivement de type unicode et str.

Les objets itérables sont parcourus à l'aide d'une boucle for de la manière suivante :

      for element in objet_iterable:        traiter(element)      

Pour une chaîne de caractère, l'itération a lieu caractère par caractère. Un caractère est une chaîne de longueur 1.

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 implémentant le protocole d'itération du langage.

Programmation fonctionnelle

Python permet de programmer dans un style fonctionnel. Les compréhensions de listes sont disponibles. Par exemple, pour construire la liste des carrés des entiers naturels plus petits que 10, on peut utiliser l'expression :

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

la liste des nombres pairs :

      l = [entier for entier in range(10) if entier % 2 == 0]      # l = [0, 2, 4, 6, 8]      

Une forme limitée de fonctions lambda, ou fonctions anonymes, est disponible :

      lambda x: x + 2      

Les fonctions lambda peuvent être définies en ligne et utilisées comme arguments dans des expressions fonctionnelles :

       filter(lambda x: x < 5, une_liste)      

retournera une liste constituée des éléments de une_liste inférieurs à 5. Le même résultat peut être obtenu avec

       [x for x in une_liste if x < 5]      

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és en arguments d'autres fonctions, et appelés lorsque nécessaire. En effet, les fonctions définies avec def sont équivalentes à celles définies avec lambda, il est d'ailleurs possible de definir une fonction à l'intérieur d'une autre fonction et ainsi obtenir une définition de fonction dans une variable locale, 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)      

Programmation objet

La programmation objet est très bien supportée par Python : 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 class. Les classes Python supportent l'héritage multiple ; il n'y a pas de surcharge statique comme en C++, mais le mécanisme des arguments optionnels et par mot-clef 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 surcharge des opérateurs

Python fournit un mécanisme élégant et orienté objet pour la surcharge des opérateurs: tout objet python peut se voir doter de méthodes dites spéciales.

Ces méthodes, commençant et finissant par deux 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__), ... 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 le mot clé print.

Les possibilités sont nombreuses et sont décrites dans la documentation du langage.

Par exemple on peut définir l'addition de deux vecteurs à 2 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

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 faire :

      def gen_fibonacci():          """Génèrateur de la suite de Fibonacci"""          a, b = 0, 1                 while True:              yield a  # Renvoi de la valeur de "a", résultat de l'itération en cours              a, b = b, a + b             fi = gen_fibonacci()      for i in range(20):          print fi.next()      
L'exécution de renverra
      def gen_nombres_pairs():          """Générateur de nombres pairs"""          a = 0          while True:              print "Génère le nombre", a              yield a              a += 2             pi = gen_nombres_pairs()      for i in range(4):          print pi.next()      

Génère le nombre 0
0
Génère le nombre 2
2
Génère le nombre 4
4
Génère le nombre 6
6

Un générateur peut sembler identique à une fonction qui retourne une liste, mais contrairement à une liste qui contient tous ses éléments un générateur calcule ses éléments un par un.

Réflexivité

Grâce à un usage intensif des dictionnaires (conteneur associatif implémenté avec des tables de hachage), Python permet d'explorer les divers objets du langage (introspection) et dans certains cas de les modifier (intercession).

Typage

Le typage n'est pas vérifié à la compilation. De ce fait, des opérations sur un objet peuvent échouer, signifiant que l'objet en question n'est pas du bon type. Malgré l'absence de typage statique, Python est fortement typé, interdisant des opérations ayant peu de sens (comme, par exemple, additionner un nombre à une chaîne de caractères) au lieu de tenter silencieusement de la convertir en une forme qui a du sens. Python propose des fonctions permettant de transformer les variables dans un autre type :

      points = 3.2 # points est du type float      print("Tu as " + points + " points !") # Génère une erreur de typage      points = int(points) # points est maintenant du type int (entier), sa valeur est arrondie à l'unité inférieure (ici 3)      print("Tu as " + points + " points !") # Génère une erreur de typage      points = str(points) # points est maintenant du type str (chaîne de caractères)      print("Tu as " + points + " points !") # Plus d'erreur de typage, affiche 'Tu as 3 points !'      

De même, chaque variable devra être déclarée avant d'être utilisée.

Python propose aussi un mécanisme de typage fort grâce à l'API trait ou au design pattern decorators.

Compilation

Il est possible d'effectuer une analyse statique des modules Python avec des outils comme Pylint 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 surcharge 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__.

Il est aussi possible de générer un Bytecode Python.

Des outils comme PyInstaller ou d'autres plus spécifiques comme Freeze sous Unix et py2exe sous Windows permettent de « compiler » un programme Python sous forme d'un exécutable comprenant le programme et un interpréteur Python. Le programme ne tourne pas plus rapidement (il n'est pas compilé sous forme de code machine) mais cela simplifie largement sa distribution, notamment sur des machines où l'interpréteur python n'est pas installé.

Modèle objet

En python tout est objet, 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

Le modèle objet de Python est inspiré de celui de Modula-3. 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. Il permet par ailleurs un traitement orthogonal des méthodes et fonctions.

Python reconnaît trois types de méthodes :

  • les méthodes d'instances, 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 classes, qui reçoivent comme premier argument la classe où elles ont été définie. 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'objet dict.
  • les méthodes statiques, qui ne reçoivent pas de premier argument implicite. Elles sont similaires aux méthodes statiques que l'on trouve en Java ou C++.

Visibilité

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 librairie 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 (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ématiques d'accesseurs et le masquage des données comme il est courant de le faire en C++ par exemple.

Héritage

Python supporte l'héritage multiple. Depuis la version 2.3, il utilise l'algorithme C3, issu du langage Dylan, 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.

Page générée en 0.166 seconde(s) - site hébergé chez Contabo
Ce site fait l'objet d'une déclaration à la CNIL sous le numéro de dossier 1037632
A propos - Informations légales
Version anglaise | Version allemande | Version espagnole | Version portugaise