Site original : Sam & Max: Python, Django, Git et du cul
Ceci est un post invité de Salvatore posté sous licence creative common 3.0 unported.
Javascript est devenu le langage incontournable du Web. C’est un langage suprenant, avec lequel, entre des mains expertes, il est possible de réaliser des choses impressionnantes.
Néanmoins, pour des tas de raisons, il s’avère encore compliqué de créer et maintenir des projets d’envergure. De plus, de nombreux développeurs sont allergiques aux bizareries de Javascript.
Il existe depuis longtemps des solutions permettant d’éviter de programmer directement en Javascript.Le site http://altjs.org/ référence de nombreuses solutions dans ce sens.
Bien entendu, je me suis intéressé aux solutions ‘Python to Javascript’. Parmi ces projets, trois, selon moi, sortent du lot : Brython, Skulpt et RapydScript.
Le but de Brython et Skulpt et de s’affranchir totalement de Javascript.
Brython pousse le concept très loin, il permet d’utilier la balise <script lang=”python”></script> directement dans une page web. Il s’agit vraiment d’un formidable projet.
Si Brython et Skulpt sont si bien, pourquoi mettre en avant RapydScript ?
En fait, la particularité RapydScript est qu’il ne tente pas de s’affranchir de Javascript, bien au contraire. La syntaxe est ‘pratiquement’ celle de Python, mais il permet d’introduire du Javascript de façon totalement transparente.
Pour ceux qui ne sont pas dérangés par la langue de Shakespeare voici l’adresse du site officiel: https://bitbucket.org/pyjeon/rapydscript
J’ai mis en ligne un page contenant quelques applications réalisées avec RapydScript : http://salvatore.pythonanywhere.com/RapydScript
Voici encore un autre exemple, qui montre la facilité avec laquelle
on peut intégrer les librairies Javascript ici ‘canvas.js’:
http://salvatore.pythonanywhere.com/RapydBox (à voir avec Firefox ou Safari)
Le code Javascript produit est très lisible comme le montrent les exemples suivants:
def sumList(L): if len(L) == 0: return 0 else: head, tail = L[0],L[1:] return head + sumList(tail) def factorial(n): if n == 0: return 1 return n * factorial(n-1)
Une fois compilé voici le code Javascsript produit:
function sumList(L) { var head, tail; if (len(L) == 0) { return 0; } else { _$rapyd$_Unpack = [L[0], L.slice(1)]; head = _$rapyd$_Unpack[0]; tail = _$rapyd$_Unpack[1]; return head + sumList(tail); } } function factorial(n) { if (n == 0) { return 1; } return n * factorial(n - 1); }
RapydScript n’est pas un gadget, on peut l’utiliser pour développer de
véritables projets.
Et pour terminer, vous pouvez utiliser node-webkit pour packager et diffuser vos programmes.
A vous de jouer…
Quand on apprend un nouveau langage de programmation, on apprend d’abord les bases. Et pour la plupart des langages, elles sont communes : déclarer une variable, faire des conditions et des boucles, faire des fonctions, importer un code d’un autre fichier, etc.
Ce qui va différencier le moment où vous savez programmer dans CE langage, ce sont des notions qui lui sont spécifiques et que vous commencez à maitriser.
Voici 5 notions spécifiques au langage qu’il faut apprendre en priorité si vous voulez pouvoir dire “je code en Python” :
Pip est la moyen le plus utilisé d’installer une bibliothèque externe dans l’environnement Python. Dès qu’on veut faire un projet sérieux, on en a besoin. Tellement qu’il va en fait être inclus par défaut dans Python 3.4.
Virtualenv permet d’isoler plusieurs installations de Python. A partir du moment où l’on travaille sur plusieurs projets en même temps, il devient vite indispensable. Mais personnelement, je l’utilise même quand je n’ai qu’un projet installé sur une machine car il me permet de le séparer du setup Python du système et d’utiliser des hooks.
Un outil qui a été ajouté dans la lib standard en Python 3.3. J’apprécie que le pragmatisme de l’évolution de Python qui intègre petit à petit les projets qui se sont révélés les outils de facto dans la communauté.
Lire l’article sur virtualenv.
J’ai envie de dire l’itération en générale, mais c’est un très vaste sujet, et il est couvert en grande partie par les 3 derniers points.
La liste en intention, ou liste en compréhension, est une manière de boucler sur un itérable (souvent une liste), avec optionellement un filtre, afin de produire une nouvelle liste. En une ligne.
C’est stylistiquement la marque de fabrique de Python (même si c’est piqué à Haskell). C’est également ce qui le rend aussi expressif. On peut presque coder tout un programme en déclaratif avec des enchainements de listes en intention.
C’est beau, propre, efficace et court. IN-DIS-PEN-SA-BLE.
Lire l’article sur les listes en intention.
L’unpacking est une autre fonctionalité typiquement pythonienne qui permet de prendre un itérable (souvent un tuple), et de mettre ses éléments dans des variables d’une traite.
Cela permet d’augmenter drastiquement la lisibilité des programmes.
Lire les articles sur l’unpacking.
Les générateurs permettent non seulement un énorme gain en performance, mais en plus ils autorisent le traitement itératif de flux de données dont on ne connait pas la taille en avance, voire de taille infinie. Si vous utilisez des expressions génératrices, vous pourrez le faire en déclaratif. Si vous utilisez yield
, vous pourrez cacher un algorithme complet derrière une simple boucle for
.
Tout le reste, c’est du détail. Les décorateurs, la POO, l’opérateur with
, les métaclasses, les astuces magiques pour faire ceci ou cela. C’est bien, mais ça peut attendre. Ce sont ces 5 notions, qui, bien utilisées, feront d’un programmeur un dev Python.
On peut utiliser n’importe quel objet hashable comme clé de dictionnaire en Python, pas uniquement des strings. Donc des entiers bien entendu, mais également, et c’est rarement utilisé, des tuples.
Imaginez que vous ayez une structures de données ainsi initialisée :
from random import choice, randint tags = ('personne', 'animal', 'objet') depart = {} depart = {'%s_%s' % (choice(tags), randint(0, 10)): None for x in range(10)}
Cela donne quelque chose comme ça :
{u'personne_6': None, u'personne_5': None, u'objet_9': None, u'objet_6': None, u'objet_4': None, u'personne_8': None, u'objet_2': None, u'objet_0': None, u'animal_8': None}
On voit que les clés ont ici une valeur sémantique importante : elles sont porteuses de sens.
Si vous voulez la liste des nombres utilisés, il va vous falloir changer votre structure de données : en avoir plusieurs séparées, probablement. Ou alors faire de la manipulation de chaîne à base de split()
et de casting.
Par contre, si vous utilisez un tuple comme clé, vous avez le même format pour votre dictionnaire depart
, avec les mêmes possibilités, mais en plus un accès aux clés plus complet.
Déjà le code de génération est plus simple :
depart = {(choice(tags), randint(0, 10)): None for x in range(10)}
Ce qui donne :
{(u'animal', 2): None, (u'personne', 5): None, (u'personne', 4): None, (u'objet', 6): None, (u'objet', 10): None, (u'animal', 7): None, (u'animal', 1): None, (u'animal', 10): None, (u'personne', 8): None}
Mais en prime, on peut faire ça :
for (tag, number), value in depart.items(): print tag, number, value ## animal 2 None ## personne 5 None ## personne 4 None ## objet 6 None ## objet 10 None ## animal 7 None ## animal 1 None ## animal 10 None ## personne 8 None
Bref, quand vos clés ont une valeur sémantique importante, pensez à utiliser des tuples, voir carrément, un namedtuple, qui est une structure de données trop souvent ignorée alors qu’elle est très puissante, et peut remplacer bien des classes conteneurs.
Ahhh, l’unpacking… On croit qu’on a complètement fait le tour de cette fonctionalité merveilleuse, et PAF, on découvre encore autre chose.
Par exemple, la syntaxe a été améliorée avec Python 3, et accepte maintenant un unpacking partiel !
Ca se fait en l’utilisant l’opérateur splat, c’est à dire l’étoile :
>>> l = list(range(5)) >>> l [0, 1, 2, 3, 4] >>> a, *b = l >>> a 0 >>> b [1, 2, 3, 4] >>> a, *b, c = l >>> a 0 >>> b [1, 2, 3] >>> c 4
Ca marche bien entendu également dans les boucles for
.