Python
Un article de Haypo.
« Python est à Perl ce que le système
métrique est au système anglo-saxon » — Palats
« Ce que j'aime dans Python, c'est que je peux passer l'essentiel
de mon temps de réflexion sur le code en simplifiant les idées
qui étaient inutilement tordues dans ma tête » — nil
« Chaque fois que je veux faire un truc, non seulement c'est faisable,
mais souvent c'est encore mieux que ce à quoi je m'attendais ! » — LePoulpe303
« Python est vraiment un language de flemmard » — Yoann512
« On se demande pourquoi les autres langages ont des syntaxes si compliquées » — glooze
Retour aux langages de programmation
Présentation du langage
Python est un langage de programmation interprété possédant une grande bibliothèque de fonctions (ou modules). Ayant longuement programmé en C et C++, je trouve que programmer en Python (plutôt que C ou C++) est un grand gain de temps : aussi bien pour l'écriture du code que pour sa maintenance (débogage). La gestion des erreurs (ou exceptions) est bien meilleure : un programme ne plante pas, mais une exception est levée. Après, c'est au programmeur de bien gêrer les exceptions Python !
Au niveau des désavantages, six mois d'utilisation m'ont fait remarqué un défaut récurrent aux langages interprétés : il n'est pas possible de dire que le programme est stable. Il est toujours possible qu'une fonction inutilisée dans 99% des cas soit appelée, et là ... « c'est le drâme » (cf. 20h20). Le drâme est un appel d'une fonction ... qui n'est pas définie. Ce problème est détecté à la compilation en C.
Autre désavantage : Python est un langage interprété. Du coup, il est forcément beaucoup plus lent que des langages compilés comme le C (réputé pour sa vitesse). Il existe de nombreux projets visant à accélérer Python pour le rapprocher des performances d'un programme en C. Voyez la partie ci-dessous qui est dédiée à l'optimisation.
Quelques points intéressants
Expressions régulières
Le module re permet d'utiliser facilement des expressions rationnelles. Exemple, rechercher un nombre dans une sous-chaîne (puis l'afficher) :
import re print re.compile("[0-9]+").search("a 123 b 4").group(0)
En fait, la méthode search (d'un Regular Expression Objet) renvoie un Match Objet (ou None si la chaîne ne correspond pas au motif). Cet objet a deux méthodes intéressantes : groups() qui renvoie la liste des sous-chaînes, et group(i) qui renvoie la i-ième sous-chaîne (0 étant une sous-chaîne spéciale : celle qui correspond au motif).
Astuce : Utilisez le préfixe « r » pour écrire vos expressions rationelles, sinon l'anti-slash va être mal interprété. Exemple : « r"a\[b" » recherche la sous-chaîne « a[b ».
Manipuler des tableaux
Un tableau (ou vecteur ou liste, appelez-ça comme vous voulez) s'écrit de la manière suivante :
tableau = ["victor","robert","william"]
Le premier élément porte le numéro zéro (ici : tableau[0]). On peut accéder aux derniers éléments en utilisant un index négatif, exemple : tableau[-1] désigne "william".
Astuces :
- del : Permet de supprimer un élément du tableau. Exemple : « del tableau[-1] » supprime le dernier élément d'un tableau.
- in (test) : Permet de tester si un élément est dans le tableau ou non. Exemple : le test « "romuald" in tableau » est faux.
- in (boucle) : Une boucle "pour chaque élément du tableau" peut s'écrire avec le mot clé in très naturellement. Exemple : « for prenom in tableau: print prenom »
- Copie d'un tableau : l'affectation simple fait une copie par référence, utilisez « copie = tableau[:] ». Par contre, l'astuce précédente ne fonctionne pas pour les listes de deux dimensions ou plus, il faut alors utiliser « copie = copy.copy(tableau) » (n'oubliez pas "import copy").
Exception : La fonction del et l'accès via l'opérateur [] peuvent lever une exception de type IndexError.
Méthode statique
Pour créer une méthode statique, il faut écrire une méthode sans le self, puis utiliser le mot-clé staticmethod. Exemple (pouvant servir de singleton en Python) :
class Pouet: _instance = None def __init__(self): assert self._instance == None self._instance = self ... def getInstance(): if Pouet._instance == None: Pouet._instance = _Pouet() return Pouet._instance getInstance = staticmethod(getInstance)
À partir de Python 2.4, on peut écrire tout simplement :
class Pouet: ... @staticmethod def getInstance(): ...
C'est ce qu'on appelle les « decorators ».
Les propriétés (property)
À partir de Python 2.2, on peut utiliser simuler l'existence d'un attribut d'une classe alors qu'en fait, c'est une méthode qui va être appelée lorsqu'on en lit sa valeur et une autre méthode lorsqu'on la modifie. On peut également interdire la modification ou la lecture.
class Avant: def __init__(self, heure): self._minute = heure * 60 def lireHeure(self): return self._minute / 60 def modifierHeure(self, valeur): self._minute = valeur * 60 avant = Avant(2) avant.modifierHeure( avant.lireHeure() + 1 ) class Apres(object): def __init__(self, heure): self._minute = heure * 60 heure = property(_lireHeure, _modifierHeure) def _lireHeure(self): return self._minute / 60 def _modifierHeure(self, valeur): self._minute = valeur * 60 apres = Apres(2) apres.heure = apres.heure + 1
Me dites pas que la seconde écriture n'est pas plus lisible !
- Pour n'autoriser que la lecture, utiliser : heure = property(_lireHeure)
- Pour n'autoriser que la modification, utiliser : heure = property(None, _modifierHeure)
Redéfinir les opérateurs
class Python: # Instancie un objet # cls = la classe Python et non pas l'object instancié def __new__(cls): pass # Constructeur de l'objet def __init__(self): self.items = [1, 2, 3] # Destructeur def __del__(self): print "Pourquoi tant de haine ?" # Utilisé pour : "len(p)" def __len__(self): return len(self.items) # Utilisé pour : "p[x]" def __getitem__(self, key): return self.items[key] # Utilisé pour : "x in p" def __contains__(self, value): return (value in self.items) # Utilisé pour : "for x in p" def __iter__(self): for x in self.items: yield x
Note : dans cet exemple, « return self.items.__iter__() » aurait été plus judicieux pour la méthode __iter__.
Voir aussi la documentation sur les opérateurs Python.
Manipuler différentes base (hexadécimal)
Entrée | Sortie | Méthode | Exemples |
---|---|---|---|
Hexadécimal (str) | Entier (int) | int(chaine, 16) | int("0xFF", 16) == int("FF", 16) == 255 |
Entier (int) | Hexadécimal (str) | "%X" % nombre | ("%04X" % 255) == "00FF" ou ("0x%X" % 255) == "0xFF" |
Exécuter un script avant le lancement de Python
Il y a deux endroits où on peut personnaliser Python :
- site : personnalisation globale qui permettent d'adapter Python à votre ordinateur ;
- PYTHONSTARTUP : personnalisation de l'interpréteur.
Pour la partie site, tous les répertoires du PYTHONPATH (défini via la variable d'environnement $PYTHONPATH et sys.path) sont parcourus et les scripts nommés sitecustomize.py sont exécutés. C'est à ce moment par exemple qu'on peut appeler « sys.setdefaultencoding("utf-8") ». Exemple :
$ cat << EOF >| sitecustomize.py > import sys > print "Passe en UTF-8" > sys.setdefaultencoding("utf-8") > EOF $ PYTHONPATH=$PWD python Passe en UTF-8 (...) >>> import sys; print sys.getdefaultencoding() utf-8
Pour personnaliser l'interpréteur, on peut exécuter un script via la variable d'environnement PYTHONSTARTUP. Exemple :
$ echo "answer=42" >| h2g2.py $ export PYTHONSTARTUP=$(pwd)/h2g2.py $ python (...) >>> answer 42
Pour en savoir plus, voir le module site.
Éditeur
- Vim :
- Emacs :
Voir aussi PyDev (Eclipse).
Optimiser Python
Outils ou articles traitant de l'optimisation de Python :
- pyrex : Compilateur permettant de mélanger du code C et du code Python si j'ai bien compris (?)
- psyco : Module C (pour architecture i386) qui fonctionne comme un compilateur JIT (Just In Time : compile durant l'exécution du programme). Apparement, l'empreinte mémoire est assez grosse dans la version actuelle mais les performances sont bonnes sans avoir à retoucher à son programme Python.
- PyInline permet d'ajouter du code source dans un autre langage directement dans un programme C, et de manière transparente.
- list2str : Petit histoire sur l'optimisation (en Python uniquement) d'une fonction très simple expliquant pourquoi ça va plus vite d'une version à l'autre de la fonction.
- py2cmod : Outil permettant de convertir un module Python en code C, ce qui permet de créer des versions plus performante
- weave : outil permettant d'inclure du code C/C++ dans du code Python
Destructeur et compteur de référence
Compteur de référence
L'implémentation de référence de Python (CPython) utilise un compteur de référence pour le objets. Quand le compteur tombe à zéro, son destructeur est appelé et l'objet est détruit. Mais avec certaines constructions, il se peut que le compteur ne tombe jamais à zéro :
class Fils: def __init__(self, parent): self.parent = parent class Parent: def __init__(self): self.fils = Fils(self) parent = Parent()
Le parent a une référence à son fils (parent.fils) et le fils a une référence à son parent (fils.parent). Pour cette raison, les deux objets ne seront jamais détruits ! Il faut casser la référence avec :
parent.fils = None
et/ou :
fils.parent = None
Sinon, une solution plus simple est d'utiliser weakref :
import weakref class Fils: def __init__(self, parent): self.parent = weakref.ref(parent) class Parent: def __init__(self): self.fils = Fils(self) parent = Parent()
Le parent a toujours une référence (forte) à son fils, mais le fils n'a plus qu'une référence faible à son parent. La syntaxe est différente, fils.parent est maintenant une fonction qui renvoie l'instance Parent ou None si l'instance n'existe plus.
Destructeur
Lorsqu'un objet est détruit, son destructeur (objet.__del__()) est appelé. Enfin... en théorie. En pratique, il est difficile de contrôler le moment exact où l'objet est détruit. Exemple :
def affiche(filename): for line in open(filename): print line.rstrip() print "EOF"
On peut supposer que le fichier soit fermé avant/après l'affichage d'EOF, mais ce n'est pas obligatoirement le cas. avec l'interprète PyPy, le fichier peut être fermé bien après la sortie de la fonction affiche() pour des questions de performance.
S'il est important que le fichier soit fermé au plus tôt, il faut le fermer explicitement avec sa méthode close() :
def affiche2(filename): f = open(filename) for line in f: print line.rstrip() f.close() print "EOF"
ou plus élégamment avec with :
def affiche3(filename): with open(filename) as : for line in f: print line.rstrip() print "EOF"
Python et ctypes
Lire Python et ctypes.
Python C API
Lire Python C API.
Python et Unicode
Lisez l'article dédié Python Unicode.
Module subprocess
Lisez l'article dédié Python subprocess.
Introspection
- dir(objet) : nom des attributs de l'objet
- type(objet) : type de l'objet
- getattr(objet, nom), setattr(objet, nom, valeur), delattr(objet, nom) : lire / modifier / supprimer un attribut selon son nom
- isinstance(objet, type), issubclass(objet.__class__, classe), type(objet) == un_type, callable(objet) : teste le type d'un objet
- Attributs d'une classe :
- cls.__name__ : nom de la classe
- cls.__bases__ : classes parent
- cls.__subclasses__ : classes filles (classes qui héritent de cls)
- objet.__doc__ ou help(objet) dans l'interprète interactif : documentation de l'objet
Voir aussi le module inspect.
Les différentes machines virtuelles
Python est un langage. On peut compiler du Python pour donner du code machine i386, mais on peut aussi en faire du bytecode Java, ou plus couramment du bytecode pour la machine virtuelle CPython (l'interpréteur le plus connu). Voici donc une liste de machines virtuelles permettant d'exécuter du Python :
- Jython : Exécution dans une Java Virtual Machine (JVM, voir Java). Voir aussi le projet Jpype qui permet d'utiliser du Java dans Python.
- IronPython : Dans une plateforme .NET avec intégration du Common Language Runtime (CLR)
- Parrot : Machine virtuelle en développement qui sera utilisée pour exécuter du Perl6 ou Python
- pypy : Implémentation de Python codée en Python qui se veut aussi rapide que l'implémentation en C, voir même plus en utilisant une analyse dynamique du code ...
- Stackless Python
Script intéressant : platform.py, donne diverses informations sur la plateforme exécutant le script Python.
Convertir un programme Python en ...
... un autre langage (Java, Perl, C++)
- C++ : Shedskin (voir aussi le blog de son auteur)
- C++ : Python2C, petit script très limité qui vise à convertir un script Python en C++
- C : unpython
- Perl : Perthon
- Java : Jython
- Plateforme .NET : IronPython
... un binaire (Windows / Unix)
Il est possible de compiler un script Python pour produire un programme binaire.
- Créer un binaire Windows (PE)
- Créer un binaire Unix (ELF)
- freeze.py : Inclut dans Python apparement (?)
Valgrind
Apprendre Python
Ressources gratuites
En français :
- Plongez au coeur de Python (Dive Into Python)
- Apprendre à programmer avec Python par Gérard Swinnen
- Documents pour apprendre Python : Liste de l'AFPy
En anglais :
Par le jeu
- Python Challenge
- Project Euler : Jeux mathématiques
- pygame
Ressources payantes
En français :
- Programmation Python de Tarek Ziadé : référence Python 2.4 en français accessible aux débutants en Python
- Petit guide à l'usage du développeur agile de Tarek Ziadé : bonnes pratiques pour programmer en Python (bien que les pratiques puissent s'appliquer à d'autres langages)
Voir aussi
Articles connexes
- FAQ Python — Python graphique — Python ou rien — pypy — HappyBoom — Poilu — Tachatte
Liens externes
Communautés
- AFPY : Association Francophone Python
- python.org : Le site officiel
Documentation
- docs.python.org : Documentation officielle (en anglais), avec ici un lien sur la référence de la bibliothèque officiel de Python
- Projet de traduction de la documentation officielle complète en français
- Conseils sur le style de programmation en Python (PEP 8)
- Jouer avec Unicode
- Tutoriel Python-SWIG : Comment interfacer Python avec du C ou C++
- Python et XML (aide mémoire)
Projets intéressants utilisant en Python
- Slune : Jeu de voiture en 3D codé en Python (utilise Soya3D)
- Monsterz : Jeu très sympatoche codé en Python
- IPython : Shell écrit en Python ;-)
- Gajim : Client Jabber en GTK
- Gnu Mailman : Gestionnaire de liste de diffusion
- Zope : Serveur d'application (HTTP)
- Trac : Outil « tout en un » pour la gestion de projet, c'est-à-dire : suivi de SubVersion, gestion de bug, gestion des tâches, wiki, etc.
- GRAMPS : Outil pour gérer sa généalogie
- TinyERP : Progiciel de gestion intégré (ERP) et gestion de la relation client (CRM)
- PyDDR : Jeu de danse dans le style Dance Dance Revolution
Voir aussi : les applications qui utilisent PyGTK.
De nombreux "gros" logiciels utilisent Python comme langage d'extension : OpenOffice, Inkscape, Scribus, Blender, ...
Bibliothèques
- PyMedia : Lire des fichiers Wav, Ogg, Mp3, etc.
- PyGTK : Binding Python pour GTK+
- PyQt : Binding Python pour Qt
- TwistedMatrix : Bibliothèque réseau haut-niveau très performante (et également toute une partie sur les traitements asynchrones)
- BeautifulSoup : Permet de manipuler facilement des documents HTML « accidentés » (ne respectant pas la norme du W3C)
- module
path
: Dans la même trempe queos.join
, mais en bien plus puissant. - py-fate : Framework contenant des proxys et algorithmes qui permettent d'écrire un programme résistant aux erreurs.
- PYRO : PYthon Remote Objects
- Pypar : Parallel Programming in the spirit of Python! (basé sur MPI)
Divers
- (en) Slides/Handout for "Code Like A Pythonista: Idiomatic Python" Available
- (en) pylint : Un programme note la qualité d'un code écrit en Python développé par Logilab (ceux qui bossent aussi sur PyPy)
- (en) python-dev summaries: Résumé de liste de discussion python-dev
- (fr) Créer un navigateur web avec python (8 janvier 2006)
- (en) A Light-weight Approach to Aspect Oriented Programming in Python
- (en) Python for CJK (Chinese, Japanese, Korean)
- (en) Unununium : Système d'exploitation écrit en Python (enfin, une surcouche à un OS pour l'instant)
- (en) Elisa : MediaCenter développé en Python par la société barcelonaise Fluendo (pro-formats libres tels que Ogg/Theora et Ogg/Vorbis)