Des nouvelles de mon suicide.
Par Poulet le lundi, juin 4 2007, 20:53 - Divers - Lien permanent
Non j'déconne.
Un gens normal, il poste pas sur le blog, tu lui dis "Hé, allez rolol va poster sur le blog". Moi c'est "Ah au fait, tu postes plus ?" "Non, pas d'inspiration" "Ouais c'est ce qu'on se disait.". Hyper chaleureux, merci Cygal.
Pour la peine, un lien inutile mais fendard. Peut éventuellement être utilisé pour la source qui se trouve au bout, même si je doute qu'elle présente de l'intérêt. En même temps je sais pas, je l'ai pas lue.
Maintenant, un vrai contenu (parce qu'en fait des sujets j'en ai plein, hein, j'ai juste pas envie de les partager avec vous). Je vais vous parler d'un système de typage utilisable en Python, qui présente un intérêt moyen puisqu'il reste dynamique, mais quand même. Il s'agit de traits, NON ne cliquez pas, lisez la suite (je comprends pourquoi vous foutez les liens à la fin maintenant :o).
Pour paraphraser plus ou moins bluestorm et l'éditeur du papier officiel qui cause de traits, Python utilise un système de typage dynamique, et si c'est assez cool pour un langage de scripts, ça peut être chiant pour de plus gros projets. Ouais, y'a des gens qui font des gros projets en Python, faute de langage plus crédible, ou de compétence/sérieux. On en trouve cela dit des très biens, hein, et pas que des trucs de webeux, sans viser personne bien sûr. J'vous emmerde de toute façon.
Un tel déchaînement de violence, ça fout les boules.
Bref, parmis les gros projets Python, on compte Chaco (flash). Attention, lien rigolo, haha (un vrai lien vers Chaco (pdf)). Au moment où j'écris j'ai plus trop l'impression que ça soit une killer app en Python, mais on va dire que si. Or donc, Chaco vous permet (à première vue) d'utiliser plot depuis Python, pour des raisons qui me dépassent vu que je n'utilise pas plot. Ça serait comme qui dirait bâti par dessus.
Mais le problème, c'est que les utilisateurs de Chaco (et là on va faire le lien avec le début milieu de l'article) peuvent être enclins à taper n'importe quoi pour, par exemple, changer un objet de couleur. Et faut bien les comprendre : c'est pratique de pouvoir faire monObjet.color = "red" ou monObjet.color = (1.0, 0.0, 0.0, 1.0) (encore que le dernier est chiant à taper - heureusement que je l'ai directement copié-collé de la page que vous n'êtes pas allé voir). C'est ce qu'on appelle être flexible.
Dans un langage qui l'est naturellement (et souvent un peu trop), c'est pas difficile à faire. Ce qui devient plus chiant, c'est quand on veut contrôler les valeurs que peut prendre color. Par exemple, un quatrain (mettons que ça s'appelle comme ça) avec des valeurs qui ne sont pas comprises entre 0 et 1, ça n'a aucun sens. On pourrait alors imaginer un système de contrôle de l'attribut color à l'aide des propriétés (oui on sait lasts, en définissant une méthode color= :]). Ça fait quand même pas mal de code à implémenter, avec à chaque fois pour seule éventuelle différence les types acceptés.
Donc, autant utiliser un module qui le fait déjà, non ? Et qui, en passant, l'implémente certainement de cette façon (n'avez qu'à regarder). Bien. Passons à l'exemple d'utilisation (qui est encore une fois un exemple officiel), qui me permettra d'introduire quelques particularités liées à traits :
from enthought.traits.api import Delegate, HasTraits, Int, Str, Instance
class Parent(HasTraits): # Le typage se fait en héritant... ce qui le restreint aux classes. Mais bon.
first_name = Str('') # Sans surprise, on utilise deux chaînes (qu'on initialise aux chaînes vides
last_name = Str('')
class Child(HasTraits):
age = Int # Ici, un âge entier, sans intialisation.
father = Instance(Parent) # On peut utiliser des classes comme nouveaux types.
first_name = Str('')
last_name = Delegate('father') # Le nom est celui du père ;)
def _age_changed(self, old, new): # Une particularité de traits (voir plus bas)
print 'Age changed from %s to %s ' % (old, new)
joe = Parent()
joe.last_name = 'Johnson'
# Ici, on crée un enfant, et le nom de famille sera bel et bien transmis.
moe = Child()
moe.father = joe
print "Moe's last name is %s" % (moe.last_name)
# On change l'âge normalement, et... la méthode _age_changed sera appelée
moe.age = 10
# La ligne suivante provoquera une erreur
moe.age = 12.3
Voilà voilà. Le code se comprend facilement, même pour les non-pythonnistes que sont en majorité les hérétiques qui lisent ce blog. On observe trois points importants, qui sont d'ailleurs signalés en commentaires dans le code source original, et que je vais retranscrire ici : le rôle de traits ne se limite pas au typage. C'est son but premier, que les développeurs ont appelé la “validation”. C'est ce rôle qui fera que la dernière ligne provoquera une erreur (12.3 n'étant pas un entier). Ici, les exemples d'utilisation sont basiques, mais je vous invite à consulter le site officiel si vous souhaitez en voir des plus intéressants (on peut par exemple créer des types sommes, ou des types d'entiers compris dans un certain intervalle, ou des structures de données typées (List(Int) par exemple), etc.)
Mais traits ne se limite pas à ça. Il propose aussi ce qu'on appelle la “délégation”. En l'occurence, on la voit assez facilement avec l'appel de Delegate : une classe peut hériter certaines caractéristiques (on dira "certains traits"...) d'une autre, sans pourtant passer par un héritage habituel.
Le troisième point présenté ici est la “notification” : on peut définir un comportement qui sera adopté lors de la modification d'un trait. Cela se fait en passant par une méthode qui, si elle est implémentée, devra être prête à recevoir l'ancienne et la nouvelle valeur du trait.
Bon, vous allez me dire que vous vous ennuyez vraiment, que tout ceci ne vous intéresse pas. Moi non plus, pas trop, en fait. Mais il reste un dernier point, que je n'ai pas présenté ici parce que le code d'exemple ne fonctionne pas chez moi, que les développeurs on appelé la “visualisation”. Via un module appelé traits.ui, on peut en effet définir une façon purement sémantique de représenter ses données dans une interface graphique. On donne alors la possibilité de construire une interaction avec l'utilisateur final du programme, standardisée et sans fioritures (du moins pour une utilisation basique), donc évidente et régulière. On peut interroger cet utilisateur sur la valeur qu'il souhaite donner à un certain trait, en profitant immédiatement des trois autres particularités développée précédemment. Bon, ça a une gueule sacrément austère, mais comme je vous le disais je ne suis pas sûr que ça ne soit pas modifiable pour une utilisation avancée.
Pour les personnes qui se sont vraiment emmerdées jusqu'à présent, je reviens juste quelques secondes sur le côté “délégation”. En effet, si ici les traits semblent être une joyeuse API visant à combler certaines lacunes du langage, ils sont en réalité un objet de recherche, qu'on veut utiliser dans des langages orientés objet qui pratiquent l'héritage multiple (et où, presque par définition, ça pose problème), ou même dans des langages plus raisonnables. Ils sont alors présentés comme une façon d'échapper aux problèmes de cet héritage multiple, et comme des entités dont l'utilisation permet de factoriser le code, de regrouper des comportements (mais pas des états) communs à plusieurs classes.
Voici donc un court article à ce sujet (caml inside) (pdf), qui pourra donner envie au lecteur de lire un article un peu plus riche (pdf). Ils présentent notamment (surtout le deuxième) les faiblesses des mécanismes d'héritage multiple, et l'utilisation des traits en tant que solution.
NB : Vous comprenez pourquoi j'écris plus, ça sert vraiment à rien.
Commentaires
UN REQUIN BITE §! UN REQUIN BITE §!