Faire des enums en python 59


Ceci est un post invité de Réchèr posté sous licence creative common 3.0 unported.

“Moi, je viens du C++”

Voilà un propos qui fait classe. Ça donne un air de vieux de la vieille, à qui on ne la fait pas, et qui connaît des langages que c’est pas des langages de taffioles. “De mon temps, fallait savoir ce qu’on faisait, sinon tout plantait. On ciselait notre code à la main dans des blocs de granit. Vous les gosses de maintenant, vous connaissez plus rien. Eh ! Sale jeune, au lieu d’importer des lib de feignasses, vient donc me changer ma poche à urine.

Ça aurait été encore plus classe de dire que je viens de l’Assembleur, mais je suis pas assez vieux pour ça. Et de toutes façons, en vrai, je viens du Pascal. Bref, passons.

Tout ça pour dire que dans le C++, il existe quelque chose que j’avais trouvé bien sympa : les enums.

Comment ça marche ?

Un enum est un type de variables ayant un domaine de valeur fixe et prédéfini, que l’on spécifie lors de la déclaration du type.

typedef enum
{
     Pique,
     Coeur,
     Trefle,
     Carreau
} ECouleursCartes;

Ensuite, on peut déclarer une variable de ce type, et lui affecter l’une des valeurs autorisées.

ECouleursCartes vMaCouleurCarte;
vMaCouleurCarte = Trefle;

Concrètement, chaque valeur correspond à un entier. Le compilateur fait les correspondances tout seul comme un grand.

À quoi ça sert ?

À avoir du code plus parlant quand on veut représenter des notions concrètes de la vraie vie, ou quand on implémente une machine à état.

Par exemple, vous créez une classe FeuCirculation. Vous avez besoin d’une variable renseignant sa couleur. Vous pouvez utiliser un int à l’arrache, et noter en commentaire quelque part : “0 c’est rouge, 1 c’est vert, 2 c’est orange.”. Mais c’est chiant. Il faut toujours garder en tête les correspondances. On risque d’attribuer des valeurs non documentées. Bref, y’a n’importe quoi dedans et ça pue, (un peu comme une poche à urine).

Avec un enum, tout est plus clair, aussi bien dans le code définissant la classe FeuCirculation, que dans le code qui l’utilise. Et c’est plus robuste.

L’exemple qui est donné très souvent dans les tutoriaux, c’est un enum Animal, contenant les valeurs chien, chat, bœuf musqué, ... Ça fonctionne, mais personnellement cet exemple me gêne un peu. Chaque animal est un objet à part entière. Dans ce cas, il vaudrait mieux créer une classe générique Animal, et la faire hériter. Ce qui permettra ensuite de créer des méthodes telles que manger(), crier(), péter(), ...

If it quacks like a duck, it may have noticed you are fucking it.

Pour décrire plusieurs objets, utilisez des classes. Pour décrire les différents états d’un même objet, utilisez un enum. Pour décrire plusieurs objets simples, utilisez l’un ou l’autre, c’est à vous de choisir.

Comment faire un enum en python ?

Il n’y a, à ma connaissance, pas de structure syntaxique dédiée. Mais c’est pas grave, on va bien trouver quelque chose.

Le plus simple, pour commencer, c’est de garder l’idée de la correspondance avec des entiers. Ça offre plein d’avantages :

  • On sait exactement comment ça marche à l’intérieur.
  • On peut très facilement enregistrer des enums dans un fichier ou une base de donnée, puisque ce ne sont que des nombres.
  • On peut ordonner les valeurs. À utiliser avec prudence, car ça n’a pas toujours de sens. (Dire que l’état “feu rouge” est inférieur à l’état “feu vert”, qu’est-ce que cela signifie exactement ?)

La première idée qui vient à l’esprit, c’est de créer une classe avec les valeurs dedans, et de ne plus jamais les changer par la suite.

# On l'appelle FeuCirculation et non pas FeuRouge. 
# Parce qu'un feu n'est pas forcément rouge.
# (Putain de langue française à la con qui fait n'importe quoi).
class FeuCirculation:
    ROUGE = 0
    ORANGE = 1
    VERT = 2
    ORANGE_CLIGNOTANT = 3
    TOUT_ETEINT = 4
 
feuActuel = FeuCirculation.ORANGE

C’est bien, mais chiant à maintenir. Si on veut ajouter un autre état (par exemple, FLECHE_DROITE_ORANGE_CLIGNOTANTE), et qu’on se plante dans les valeurs numériques, il y a un risque d’avoir des doublons, et ça fiche tout en l’air.

Voici un petit peu mieux :

class FeuCirculation:
    (ROUGE,
     ORANGE,
     VERT,
     ORANGE_CLIGNOTANT,
     TOUT_ETEINT,
    ) = range(5)

range(5) renvoie un tuple (0, 1, 2, 3, 4). Des entiers différents sont attribués aux valeurs de l’enum. Si on veut en rajouter une et qu’on oublie de remplacer range(5) par range(6), ça va balancer une exception. Tout va bien.

Au cas où vous demanderiez : “qu’est-ce qui m’empêche de redéfinir l’une des valeurs, à un autre endroit du code, et de foutre le bordel ?”, je répondrais “We are all consenting adults here”. (Se référer à la philosophie du python. Si besoin, ce sera l’occasion d’un autre article).

Some consenting adults. (Je peux venir ?)

Le code est beau, mais pour débugger ?

C’est un peu lourdingue. Lorsqu’on fait print feuActuel (ou lorsqu’on tape directement feuActuel dans une console pdb), c’est une valeur numérique pas claire qui va s’afficher, au lieu d’un joli “ORANGE”, “ROUGE”, …

Un petit dictionnaire de correspondance “valeur numérique” -> “nom à afficher” serait de bon aloi. Quelque chose de ce genre, à placer dans la définiton de la classe FeuCirculation :

    dictReverse = {
        ROUGE : "ROUGE",
        ORANGE : "ORANGE",
        VERT : "VERT",
        ORANGE_CLIGNOTANT : "ORANGE_CLIGNOTANT",
        TOUT_ETEINT : "TOUT_ETEINT",
    }

Fort bien. Mais n’est-ce pas un peu casse-couille ? Eh si. Des répétitions à la pelle, et dictReverse doit rester synchro avec les définitions des valeurs. C’est redevenu chiant à maintenir.

Hey, je suis Dict-Reverse, et je suis chiant à maintenir. bi-boppe eu loulaaaa.

Définition dynamique de nouveaux types

Soyons franc, j’ai piqué cette astuce ici :
http://stackoverflow.com/questions/36932/whats-the-best-way-to-implement-an-enum-in-python

Vous connaissez certainement déjà la fonction native type(). Elle renvoie le type du truc passé en paramètre. Youpi.

Mais saviez-vous qu’elle permet également de créer de nouveaux types ? Pour ce faire, il faut l’appeler avec 3 paramètres :

  • Le nom.
  • Une liste indiquant les types de base (dans le cas où on veut que le type soit hérité).
  • Un dictionnaire contenant les attributs. Les clés sont des chaînes de caractère, et correspondront aux noms des attributs.

La création de l’enum FeuCirculation pourrait donc se faire de cette manière :

FeuCirculation = type(
    "FeuCirculation",
    (),
    {
        "ROUGE" : 0, 
        "ORANGE" : 1, 
        "VERT" : 2, 
        "ORANGE_CLIGNOTANT" : 3, 
        "TOUT_ETEINT" : 4
    })
 
>>> FeuCirculation
<class '__main__.FeuCirculation'>
>>> FeuCirculation.VERT
2

On peut également ajouter le dictReverse dans le dictionnaire des attributs. (Ça fait un dictionnaire dans un dictionnaire, c’est lol).

FeuCirculation = type(
    "FeuCirculation",
    (),
    {
        "ROUGE" : 0,
        "ORANGE" : 1,
        "VERT" : 2,
        "ORANGE_CLIGNOTANT" : 3,
        "TOUT_ETEINT" : 4,
        "dictReverse" : {
            0 : "ROUGE",
            1 : "ORANGE",
            2 : "VERT",
            3 : "ORANGE_CLIGNOTANT",
            4 : "TOUT_ETEINT"}
    })
 
>>> FeuCirculation
<class '__main__.FeuCirculation'>
>>> feuxActuel = FeuCirculation.VERT
>>> feuxActuel
2
>>> FeuCirculation.dictReverse[feuxActuel]
'VERT'

Et maintenant y’a plus qu’à coder une petite fonction qui fait tout ça génériquement.

def enum(enumName, *listValueNames):
    # Une suite d'entiers, on en crée autant
    # qu'il y a de valeurs dans l'enum.
    listValueNumbers = range(len(listValueNames))
    # création du dictionaire des attributs.
    # Remplissage initial avec les correspondances : valeur d'enum -> entier
    dictAttrib = dict( zip(listValueNames, listValueNumbers) )
    # création du dictionnaire inverse. entier -> valeur d'enum
    dictReverse = dict( zip(listValueNumbers, listValueNames) )
    # ajout du dictionnaire inverse dans les attributs
    dictAttrib["dictReverse"] = dictReverse
    # création et renvoyage du type
    mainType = type(enumName, (), dictAttrib)
    return mainType
 
>>> FeuCirculation = enum(
        "FeuCirculation",
        "ROUGE", "ORANGE", "VERT",
        "ORANGE_CLIGNOTANT", "TOUT_ETEINT")
>>> FeuCirculation.TOUT_ETEINT
4
>>> FeuCirculation.dictReverse[FeuCirculation.TOUT_ETEINT]
'TOUT_ETEINT'

Une petite précision : d’habitude, quand on crée des classes ou des types, c’est pour les instancier. Là on ne le fait pas, on se contente d’utiliser des valeurs statiques contenues dans le type. Vous pourriez faire feuDuCarrefour = FeuCirculation(). Ça va fonctionner, mais ça ne vous servira à rien.

Le code de la route a parfois besoin de refactoring

Mais si on mélange les enums ?

>>> FeuCirculation = enum(
        "FeuCirculation",
        "ROUGE", "ORANGE", "VERT",
        "ORANGE_CLIGNOTANT", "TOUT_ETEINT")
>>> etatMatiere = enum(
        "etatMatiere", 
        "SOLIDE", "LIQUIDE", "GAZEUX")
>>> etatMatiere.dictReverse[FeuCirculation.VERT]
'GAZEUX'

Mince alors. Ça fait n’importe quoi, sans signaler aucune erreur. C’est normal. D’un enum à l’autre, on ne fait que manipuler des entiers, qui restent les mêmes. Les correspondances se font joyeusement, même si ça n’a aucun sens. Dans le même ordre d’idée : FeuCirculation.ROUGE == etatMatiere.SOLIDE renverra True, ce qui ne veut rien dire. Comment régler ce problème ?

Better have traffic ice than traffic jam.

Solution 1 : ne pas régler le problème

“We are all consenting adults here”, on ne va donc pas compliquer le code en rajoutant des sécurités de partout, sous prétexte d’empêcher des erreurs. Le seule moyen valable de se prémunir de faire n’importe quoi quand on code, c’est tout bêtement de rester concentré et de faire gaffe à ce qu’on fait.

Honnêtement, ça ne m’est jamais arrivé de mélanger des enums entre eux. Pourtant, je n’ai pas la prétention de tout faire juste et sans bugs du premier coup. Parmi mes bourdes préférées : copier-coller la ligne du dessus et ne pas faire les bons remplacements (les “x” par des “y”, les “1” par des “2”, etc.), ou encore : déclarer une fonction, lui faire renvoyer un résultat bidon parce que je préfère la coder plus tard, et oublier que je ne l’ai pas codé.

def calculDist(point1, point2):
    distX = point1.x - point1.x
    distY = point2.x - point2.x
    return math.sqrt(distX * distX + distY * distY)
    # ami lecteur, sauras-tu trouver tous les fails
    # présents dans cette fonction ?
 
def RemoveDoubleLetters(strValue):
    # TODO : coder le truc. Mais là, j'ai la flemme.
    return strValue

BSOD !!

Pour limiter les risques de mélange, voici quelques conseils :

  • Préfixez les variables contenant une valeur d’enum : feu pour FeuCirculation, emat pour etatMatiere, etc. De cette manière, les erreurs de code sautent aux yeux. (making wrong code look wrong, tout ça…)
  • Il est important de ne pas polluer inutilement l’espace de nommage. Dans un fichier donné, n’importez pas les enums dont vous n’avez pas besoin. De cette manière, une erreur sera renvoyée si jamais vous utilisez une valeur d’enum imprévue. Je doute que vous ayez besoin, dans un même fichier de code, de renseigner des états de feux rouge et des états de matière.
  • Si vous faites exprès de mélanger des enums, en pensant que vous n’avez aucun moyen de faire autrement, c’est qu’il y a, dès l’origine, un problème de conception dans votre code.

Vieng fayre toi-même leu mélainge des enums, sur les muuuurs deu la cabaneu du côdeur. Vieng t'assouar.

Solution 2 : des enums fortement typés.

Au lieu que les valeurs internes des enums soient de simples entiers, on crée un type pour chacune d’elle. Comme ça, on est sûr que ça renverra une erreur si on se confusionne. Par contre, on perd en simplicité, et ce n’est plus aussi simple pour la sérialisation.

Soyons fous, et voyons ce que ça donne !

def strongTypedEnum(enumName, *listValueNames):
    # création d'une liste de type. sans attribut, sans héritage.
    # le nom du type est composé du nom de l'enum et du nom de la valeur,
    # séparés par un point.
    listValueTyped = [ type(".".join((enumName, nameValue)), (), {})
                       for nameValue in listValueNames ]
    # Ensuite, c'est tout pareil que la fonction d'avant.
    dictAttrib = dict( zip(listValueNames, listValueTyped) )
    dictReverse = dict( zip(listValueTyped, listValueNames) )
    dictAttrib["dictReverse"] = dictReverse
    mainType = type(enumName, (), dictAttrib)
    return mainType
 
>>> FeuCirculation = strongTypedEnum("FeuCirculation",
        "ROUGE", "ORANGE", "VERT",
        "ORANGE_CLIGNOTANT", "TOUT_ETEINT")
>>> etatMatiere = strongTypedEnum(
        "etatMatiere", 
        "SOLIDE", "LIQUIDE", "GAZEUX")
>>> etatMatiere.LIQUIDE
<class '__main__.etatMatiere.LIQUIDE'>
>>> etatMatiere.dictReverse[FeuCirculation.ROUGE]
Traceback (most recent call last):
  File "<pyshell#20>", line 1, in <module>
    etatMatiere.dictReverse[FeuCirculation.ROUGE]
KeyError: <class '__main__.FeuCirculation.ROUGE'>

Mais est-ce bien nécessaire ?

Y’a une lib pour ça

Comme toujours, avec cette foutue prolifération de code libre, dès que quelque chose de cool peut potentiellement exister, un connard de geek l’a déjà fait, vous privant de l’occasion de le faire vous-même et de retirer la gloire qui en décombe. La lib flufl.enum permet donc de créer et manipuler des enums, avec autant et même plus de fonctionnalités que ce que je viens de décrire ici. (Connards de geeks qui viennent manger le pain des français).

Par contre, j’ai regardé le code, et j’ai pas pigé comment ça fonctionnait à l’intérieur. Ça fera peut-être l’objet d’un autre article, si j’ai le courage de me plonger dedans, et que je trouve ça intéressant et rigolo.

De toutes façons, les libs c’est chiant, ça ajoute des dépendances, il vaut mieux tout coder à la main.

Disgression 1 : quelle classe ce type !

Déclarer un type avec la fonction type(), et déclarer une classe, ça ne fait pas exactement la même chose.

>>> class MaClasse:
	pass
 
>>> MaClasse
<class __main__.MaClasse at 0x011CB270>
>>> instanceClasse = MaClasse()
>>> instanceClasse
<__main__.MaClasse instance at 0x011C8BC0>
 
>>> MonType = type("Le_Nom_De_Mon_Type", (), {})
>>> MonType
<class '__main__.Le_Nom_De_Mon_Type'>
# Hey ! Le nom est dans une string, et y'a pas d'adresse mémoire !
 
>>> instanceType = MonType()
>>> instanceType
<__main__.Le_Nom_De_Mon_Type object at 0x011C1B30>
# Hey ! C'est un object, et pas une instance !

Ça a peut-être quelque chose à voir avec une histoire de old-style class et new-style class. J’ai pas cherché plus loin pour l’instant. Ça fera peut-être l’objet d’un autre-autre article, si j’ai le courage de me plonger dedans, et que je trouve ça intéressant et rigolo.

Disgression 2 : Restons dans les règles

J’avais trouvé un autre exemple de machine à état, plus rigolo que des feux de circulation ou de la matière. Je ne m’en suis pas servi durant mes explications, parce que ça aurait distrait le lecteur / la lectrice (charge cérébrale, tout ça…). Mais ce serait vraiment dommage de ne pas vous en faire profiter. Le voici donc :

>>> PhaseCycleUterin = enum(
        "PhaseCycleUterin",
        "PREPUBERE", "MENSTRUELLE", 
        "OVULATION", "PROLIPERATIVE", "SECRETRICE"
        "ENCEINTE", "MENOPAUSE")
 
>>> etatMatiere.dictReverse[PhaseCycleUterin.MENSTRUELLE]
'LIQUIDE'

Voilà, ce sera tout pour aujourd’hui. La prochaine fois, nous redéfinirons le type “object” en utilisant uniquement les picots du langage Braille.

Une femme qui a ses règles.


About recher

Ouvrier-codeur dans une start-down experte en solution de karmagraphie logicielle. Inventeur d'un langage de programmation permettant de coder en alsacien. Ardent défenseur du mot "chevals". Membre du bar (mais pas du foo).

59 thoughts on “Faire des enums en python

  • Sam

    J’en profite pour ajouter une astuce:

    >>> from collections import namedtuple
    >>> FeuDeCirculation = namedtuple('FeuDeCirculation', ('Bleu', 'Rouge', 'Mauve', 'Pourpre', 'Parabolique'))(*range(5))
    >>> FeuDeCirculation
    FeuDeCirculation(Bleu=0, Rouge=1, Mauve=2, Pourpre=3, Parabolique=4)
    >>> FeuDeCirculation[2]
    2
    >>> FeuDeCirculation.Parabolique
    4
    >>> FeuDeCirculation._fields
    ('Bleu', 'Rouge', 'Mauve', 'Pourpre', 'Parabolique')

    Et pour les fans des one liners:

    >>> from collections import namedtuple
    >>> enum = lambda name, *args: namedtuple(name, args)(*xrange(len(args)))
    >>> FeuDeCirculation = enum('FeuDeCirculation', 'rouge', 'pas_rouge', 'autre')
    >>> FeuDeCirculation
    FeuDeCirculation(rouge=0, pas_rouge=1, autre=2)
  • recher Post author

    Youpi, mon article vient d’être publié ! Merci !

    Je vous invite à laisser votre curseur de souris sur les images, pour découvrir un surcroît de subtilités croquignolettes.

    Et merci aussi pour l’astuce du namedtuple, je connaissais pas. Je vais voir si y’a moyen de lui faire ressortir les valeurs littérales (pour le debug).

  • roro

    Heureusement que je lis les articles dans le mail..! Parce que, aprés le visionnage de la première image…Plus rien n’est possible. Heu…si, tout est possible..Heuh..Non…Si…Boouuh!
    Où’c’qu’il est le bouton “Sign’allez!”
    Ce Recher est un orfèvre !

  • Sam

    J’ai juste halluciné à la relecture avant publication quand je suis passé du titre “Faire des enums en Python” aux tags qu’il avait choisi: animaux zoophiles bbw enum fesses python seins type…

  • anon

    J’étais concentré puis j’ai vomit sur mon écran au passage des adultes consentant.
    Merci quand même, ça m’a donné une idée de design.

    De toutes façons, python je m’en fous, je préfère un bon vieux php qui s’accouple vigoureusement avec une bonne dose de JS crade mais jouissif et puis la vigueur de la jeunesse vaut mieux que vos langages de retraités

    >P

  • Sam

    Ca fait un bout de temps que je cherchais une occaz pour le placer celui-là.

  • Bronco


    Comme toujours, avec cette foutue prolifération de code libre, dès que quelque chose de cool peut potentiellement exister, un connard de geek l’a déjà fait, vous privant de l’occasion de le faire vous-même et de retirer la gloire qui en décombe.

    1- c’est le drame de ma vie ^^ (j’ajouterais qu’en plus cette saloperie l’a fait mais en mieux ! )
    2- ce serait pas plutôt qui en découle ?
    3- le trombone à la word, c’est de la provoc’, c’est ça ? ^^

  • anucunnilinguiste

    Moi j’aime pas les enums, y un côté variable globale que j’aime pas, esthétiquement parlant…mais c’est seulement parce-que j’ai fait une soirée digo et que j’ai pas tout compris ;), mais je vous aime quand même et demain je promets, je relis l’article avec la branlette C++ et assembleur en intro ;)

  • anucunnilinguiste

    Ce que je préfère quand même par dessus tout sur ce blog ce sont les références du type : PhaseCycleUterin.MENSTRUELLE. J’aime ressentir l’ambiance des cercles philosophiques des Lumières, à côté de cela, les think-tanks sionistes c’est pour les gamins ;)

  • anucunnilinguiste

    J’en profite pour glisser une quenelle de 175, j’espère que vous ne m’en voudrez pas…

  • oldschool

    Les gars je vous adore, mais si vous êtes prêts à acheter la licence Sublime Text 2, par pitié, achetez aussi celle d’Antidote. Mes yeux vont remercieront chaleureusement !

  • Sam

    Et encore, on s’améliore avec le temps. Mais c’est vrai que ma génération est vraiment pas appliquée en orthographe.

    Tu peux devenir correcteur si tu veux ! On a déjà le soutient de deux lecteurs mais c’est un gros boulot, un 3e serait pas de refus.

  • oldschool

    “Moi, je viens du C++”, faut pas s’en vanter de cela en général, ça veut dire qu’on code comme des merdes…Le C++ ;) des barres, encore le C ou l’ADA je dis pas mais le C++ franchement ! Le C++ un langage de gros batard ;)

  • oldschool

    “Tu peux devenir correcteur si tu veux ! On a déjà le soutient de deux lecteurs mais c’est un gros boulot, un 3e serait pas de refus.”

    Je le ferais à l’occasion pour les énormités…mais sincèrement si vous voulez soutenir le boulot gigantesque entrepris depuis des dizaines d’années par des pros soutenez Antidote, multi-plateforme, intégré à Word, Libre Office, Thunderbird, Firefox…

    Je sais que vous êtes soucieux de l’esprit pédagogique de vos articles, mais ce qui ce qui se conçoit bien s’énonce clairement – Et les mots pour le dire arrivent aisément…En algorithmie comme en programmation, il me semble que cela prend tout son sens.

    Attention, j’adore votre site, cela est plutôt à considérer comme une suggestion s’intégrant dans le processus ITIL de la gestion qualité en vue d’une meilleure synergie entre les centres de profit. Demain j’arrête les cigarettes de Noël !

  • oldschool

    “Décidément, la tirade de Recher sur le libre à l’air de plaire”, je croyais que tu parlais de cela : “Le C++ un langage de gros batard ;)” ;)

  • anucunnilinguiste

    Sam et Max j’aime trop votre style de boule les mecs !

  • anucunnilinguiste

    C’est moi qui aurait du gagner le cadeau de toute façon. Bisous sur votre couille gauche, eh oui j’alterne les couilles. Je suis un vrai démocrate !

  • Sam

    @oldschool: je ne conteste pas, la forme est importante. Pas sûr qu’un outil change énormément la donne, mais je vais voir si il y a moyen d’intégrer la bouzin à wordpress. Attention cependant, il y a autant de rédacteurs que de niveau d’orthographe et que de patience à la relecture, donc n’attendons pas de miracle. Mais il faut le tenter.

    @anucunnilinguiste: heureux que tu sois heureux. Quand on tient un blog, les compliments sont hyper agréables.

  • cruciverbiste

    Ici j’aime bien parce que je me sens comme chez moi, c’est le bordel !

  • oldschool

    On va pas en faire un roman façon BHL mais dans la phrase : “Attention cependant, il y a autant de rédacteurs que de niveau(x) d’orthographe”, en tant qu’intégriste barbu adepte de la charia et du bondage façon papayou, pour moi il y a le niveau d’orthographe ou pas. Ce n’est pas une calamité mais il faut tendre vers le haut, sinon on se retrouve avec Pujadas et son pote au crâne chauve qui sort des chiffres de son Ipad :) et j’ai horreur des Ipad :). Mais je suis comme l’adorateur des anus, je vous aime surtout avec des poils autour !

  • anucunnilinguiste

    Et des blogs, j’en ai vu…j’en écrivais même en 1999 quand ça se nommait pas blog ;) genre en cgi ;), mais c’était le même fonctionnement !

  • Sam

    @oldschool: bon pour antidote c’est mort: 119 euros pour une version monoposte et en plus faut se déplacer pour acheter… le CD. Dans tous les cas je penses pas que l’orthographe soit une question de niveau: on connait tous la plupart des règles, c’est juste qu’on écrit avec peu d’application. Ce n’est pas une excuse hein, juste une raison.

  • anucunnilinguiste

    Bon faut dire que je suis un vieux, les gars comme moi on attendait 4 à 6 mn pour une page avec des gifs et on payait 2000 à 3000 francs par mois en conso téléphone, on surfait avec Mosaic chez Compuserve ! T’oserais plus montrer ça à un jeune de 17 ans avec son Iphone ;), il dirait que t’es “swag” !

  • oldschool

    Multi-plateforme, durable dans le temps avec une charmante canadienne au support avec une voix digne des meilleurs Dorcel en cas de problème, cela n’a pas de prix ! Si tu préfères la frigide de SFR, c’est toi qui choisis !

  • oldschool

    En tant qu’irresponsable de service informatique, je recommande Antidote et l’impose, uniquement pour ne pas avoir à lire les torchons orthographiques quotidiens (90 emails par matinée) de mes jeunes collaborateurs pseudo ingénieurs, incultes et analphabètes et encore je suis gentil, je ne parle pas de leur incompétence flagrante et manifeste en Merise, algorithmie et analyse objet dissimulée derrière une diarrhée d’environnements de développement les plus abscons les uns que les autres.

  • anucunnilinguiste

    Un vieux comme moi tu lui dis “cross-fire” il te réponds “3Dfx” ;), l’histoire informatique est un éternel recommencement !

  • anucunnilinguiste

    @oldschool, bon dans mon dernier commentaire, j’ai mis “il te réponds”, grave erreur de ma part, il faut écrire : “il te répond”, en fait je le savais mais je me drogue avec des cigarettes de Noël et j’ai pas eu le temps de me relire car ma bru m’en a fait une petite sans filtre (pipe)…sans rancune.

  • anucunnilinguiste

    C’est bien connu la pipe de 2h30 du mat, elle tue l’orthographe ! Même chez ces dégénérés syphilitiques de flamands de Belgique ils savent ça ;), vous remarquerez que j’ai épargné les ch’tis, c’est mon côté grand-seigneur !

  • anucunnilinguiste

    De toute façon l’orthographe c’est pour les élites. Les pauvres, incultes et assimilés on les reconnait vite, pas besoin qu’ils écrivent ou s’expriment, ils ont souvent l’étoile jaune de la C.A.F. ou du chômage et/ou un survêtement Panzeri (ça existe encore ça au fait, je vous rappelle que je suis vieux ?) , je trouve que je fais bien le gars de droite. Vivement Coppé !

  • oldschool

    @Sam ton scepticisme envers Antidote était le mien envers Sublime Text 2 (je considérais ce soft comme de la branlette marketing orientée Design façon Apple touch) : j’ai acheté Sublime Text 2 quand il a changé et amélioré ma façon de travailler (trop de qualités à énumérer). Sincèrement, sans prosélytisme, je trouve que ce logiciel (Antidote) améliore la qualité des logiciels. On ne peut pas s’émerveiller devant un générateur de documentation de qualité (Sphinx au hasard) ou un environnement de développement de tests unitaires si on ne prend pas en compte non plus la qualité rédactionnelle de la documentation, pour moi il faut être cohérent sur toute la ligne. La qualité d’ingénierie doit être stable sur toute la ligne de production. Franchement, au quotidien, vous utilisez les bibliothèques sans aucune documentation ou une documentation pourrie ? Non. Et puis chez Antidote si tu galères avec une mise à jour ou que tu as rien compris, la gonzesse de chez Dorcel et bien elle te refile une licence toute propre sans galère. J’ai acheté ce soft il y a 6 ans et je paie toutes les mises à jour car il me sert professionnellement (emails, courriers de qualité) et personnellement (correction gmail, thunderbird…)(corrige mes textes de blog en rst).

  • oldschool

    119 euros, franchement qu’est-ce que c’est ? Une pute c’est 50 la demi-heure ou 100 euros l’heure ? Tu préfères un texte propre ou une chatte propre ? Vous l’aurez voulu (c.f : ligne éditoriale).

  • oldschool

    @anucunnilinguiste
    @sam

    Je crois que je vais rester ici un peu, j’aime bien l’ambiance et puis j’aime l’humour à base d’enfant sacrifié et de poils pubiens, ça me rappelle mes 13 ans en colonie chez les jésuites pédophiles.

  • oldschool

    @Sam, je te rassure, pour acheter Antidote, pas besoin de se rendre au Canada, sauf si tu cherches de la chair fraîche facile qui adore les français.

  • anucunnilinguiste

    Un tuto script sur un crawler de pron y a que ça de vrai en 2012 ;)

  • anucunnilinguiste

    Y a 10 ans, y avait un gars qui avait fait un script pour pomper du pron facile en Python…je me souviens plus du site ni du nom du script mais il était efficace…les plus anciens doivent s’en souvenir !

  • anucunnilinguiste

    Ca devait être un gars trop bien zappé pour le far-west…

  • noob

    Est-ce que les structures servaient pas justement à faire du “faux” objet ?

  • Recher

    Ouahou, je pars me coucher, je reviens, et je vois qu’une multitude de commentaires a spawné.

    Allez, je réponds 2-3 choses en vrac :

    – Les fautes d’orthographes, c’est mal, mais c’est pas le pire qu’on puisse faire à la langue française. Le pire, c’est les phrases syntaxiquement incorrectes, qui ne veulent rien dire du tout parce que l’auteur ne s’est pas relu.

    – L’autre pire, c’est le “parler moche”, lorsqu’il est utilisé sans aucune ironie, en croyant vraiment que ça fait bien de parler comme ça. http://www.dicomoche.net/. Par exemple, j’ai un collègue qui utilise des mots inutilement compliqués pour avoir l’air savant. Il dit “volumétrie” au lieu de “volume”, “problématique” au lieu de “problème”, “méthodologie” au lieu de “méthode”, etc. Je trouve ça pire que des fautes d’accords, de grammaire ou autre.

    – Je connais pas Antidote. Si des gens veulent que ce blog bénéficie des lumières d’Antidote, ils peuvent offrir une licence d’Antidote.

    – Héhé, ma citation s’essaime à travers le monde. Youpi !

    – Oui, on devrait sûrement dire “qui en découle” et pas “qui en décombe”. C’était une référence subtile à un sketch des inconnus.

    – “Le C++ un langage de gros batard ;)”. C’est ballot, ça partait bien, comme début de troll, mais le reste des commentaires n’ont pas suivi. Je vais tenter de le relancer d’une autre manière. (Voir le paragraphe suivant).

    – L’ADA c’est vraiment un langage qui sert à rien. J’en ai fait durant un TP de 4 heures pendant mes études. On avait codé une variable int qui ne pouvait jamais être impaire. Génial. En plus, ce langage a été créé par une gonzesse. (We put a troll inside a troll, etc).

    – Un crawler pron en python, bonne idée. Mais faut pouvoir choisir les catégories souhaitées. Je cocherais bien évidemment la case “BBW : Big and Beautiful Woman”.

    – Bisous sur la couille centrale. (Sociopolitiquement parlant, je suis un crypto-bourgeois de l’extrême-centre).

  • Sam

    Ok les gars, je suis con et vaincu. Donnez moi la démarcher pour essayer antidode quelques semaines légalement (sans avoir à utiliser un CD car ça fait une paie que j’ai plus de lecteur) histoire de savoir si je débourse, car je trouve pas sur leur site tout pourri.

  • Sam

    Putain recher, tu viens de te faire linker par sebsauvage à cause de ta fameuse citation. En fait t’aurais mieux faire d’écrire juste cette partie là, ça t’aurais fais moins de boulot.

  • ricardo

    C’est que c’est le vendeur officiel de ce soft, pour cela que je te donne le lien…C’était pas du genre : “vas-y demmerde-toi” ;)

  • Sam

    Ouai, je me suis un peu énervé à cause d’eux en fait. Ils vivent de ça, et ils sont pas foutu de mettre en avant un lien pour ACHETER leur produit. Bordel, je veux essayer leur bouzin, et pas moyen de le faire. C’est un monde quand même.

    Si je pirate ce logiciel, je l’aurais immédiatement. Ils n’ont rien compris à la vie.

  • Réchèr

    Le plan diabolique de détrônage de SebSauvage est en cours ! Il est subrepticement en train de se faire envahir et il ne s’en rend même pas compte. Mouhahahahaaaaaa.

    Lent basse a d’heure de l’ass-en-beurre.

  • Max

    En fait on peut y noter 2 citations “qui nous décombre” -> les inconus Les Flics et “viennent manger le pain des francais” de Fernand Renaud – Le Boulanger .

    Très bonne culture…

    PS: peut etre coluche pour la deuxieme car elle y ressemble aussi

  • roro

    hey, avec “Antidote” prenez un “Taille-doigts”, rapport à ces P…n de touches de pc, qu’ils auraient pu faire coniques, s’ils avaient étés moins cons.

  • maxime-esa

    Pour en revenir à l’article, un autre oneliner parce que “enumerate” c’est mieux que “(x)range” pour créer des énumérés, non?

    enum = lambda *x: type(”, (), dict({b:a for a, b in enumerate(x)}.items() + {‘image': {a:b for a, b in enumerate(x)}}.items()))

    >>> feu=enum(‘rouge’, ‘vert’)
    >>> feu.rouge
    0
    >>> feu.image[feu.vert]
    ‘vert’

    Et en Ada, c’est encore mieux:

    type Feu is (rouge, vert, orange);

    Et tout ca est built-in:

    Feu’Pos(vert) = 1
    Feu’Val(2) = orange
    Feu’Succ(rouge) = vert
    Feu’Image(rouge) = “rouge”

  • JeromeJ

    Oh les gars, dans FeuMachin = enum("FeuMachin", …) vous avez remarqué que vous deviez écrire 2 fois FeuMachin ? La loose :o (c’est mon côté maniaque)

    Y aurait pas moyen de faire un ptit décorateur pour ça ? :)

    @Enum
    class FeuMachin:
        enum=("lolz", "lulz")

    Et puis enum existe déjà dans les builtins (donc booh méchant pas beau d’override nos outils :( ) et ça n’a rien à voir :o (donc j’ai pas lu l’article avant pensant que ça n’avait rien à voir) Rhalala.

  • Sam

    Moi je fais encore plus simple: pas d’enum. Au pire des dicos, et pas d’int, que des slugs des valeurs textuelles. C’est plus lent, mais tellement plus pratique pour le debug.

  • Etienne

    @recher
    Merci! Chouette l’usage de type (et chouette aussi le coup du “strongTypedEnum”).

  • Selso

    Bonjour,

    Quelle prise de tête n’empêche, de la masturbation de cervelle compulsive.

    Bon sinon pour le C++ et l’énum chien, chat,… etc. Ca peut être utile si tu souhaites que l’utilisateurs manipule que ta classe animal, en fournissant cette dernière et une factory avec en paramètre un enum pour désigner l’objet à créer.

Leave a comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.