J'ai trouvé un moyen simplement de mettre en œuvre (pirater) un énumé dans Python: i peut ensuite appeler ceci comme tel: p> sexy! p> D'accord, je veux maintenant pouvoir obtenir la valeur numérique si elle est donnée une chaîne ou une chaîne si elle est donnée une valeur numérique. Disons que je veux que les chaînes correspondent exactement à la clé Enum's P> Le meilleur que je puisse penser est quelque chose comme ceci: p> ou quelque chose comme que (ignorer comment j'attrape des cas invalides) p> existe-t-il une meilleure façon de faire une meilleure façon de faire ce que je fais au-dessus? Ou ce qui précède est-il déjà aussi concis que possible. P> Il semble qu'il y ait une meilleure façon de le faire. P> p>
7 Réponses :
Vous pouvez utiliser des dictionnaires:
class MyEnum: VAL1, VAL2, VAL3 = range(3) __toString = { VAL1 : "VAL1", VAL2 : "VAL2", VAL3 : "VAL3" } @classmethod def tostring(cls, val): return cls.__toString.get(val) @classmethod def fromstring(cls, str): i = str.upper() for k,v in cls.__toString.iteritems(): if v == i: return k return None print MyEnum.tostring(MyEnum.VAL1) print MyEnum.fromstring("VAL1")
Les doubles traits de soulignement (= Nom Mangling) sont ... Eh bien, pas mal, mais je n'ai jamais vu ce cas hypothétique où ils ont un petit avantage, par opposition à l'utilisation d'un cas habituel où ils pausent des choses.
@delnan. Je vais prendre note de cela.
Eh bien, voici ce que vous avez demandé:
class MyEnum: VAL1, VAL2, VAL3 = range(3) @classmethod def tostring(cls, val): for k,v in vars(cls).iteritems(): if v==val: return k @classmethod def fromstring(cls, str): return getattr(cls, str.upper(), None) print MyEnum.fromstring('Val1') print MyEnum.tostring(2)
Myenum.tostring (3) ne renvoie aucun. Je devrais probablement être myenum.tostring (myenum.val3)
C'est parce que plage code> commence à 0.
tostring (2) code> donne
val3 code>. Noms malheureux (
* [1-9] code>). AFAIK, C / C ++
Enum code> commence à 0 aussi.
@delnan vrai. J'étais confus d'un test que j'ai fait de mon côté. Probablement un effet secondaire qui m'a empêché d'utiliser un INT directement dans la méthode de totrage.
"Tostring" et "FromsRing" sont certainement javesque. Python n'a pas besoin de ce cruft.
Je pense qu'un attributeError code> doit être soulevé dans
itstring () code> quand il n'y a pas d'attribut avec le nom propre au lieu de renvoyer
Aucun code>.
Pas une bonne idée donne des noms de variables qui conflit avec intégré - comme vous l'avez fait avec str code>.
@Martineau: Comme je l'ai dit, c'est ce que l'op a demandé i> pour. Je voulais juste montrer comment utiliser les fonctionnalités dynamiques de Python pour raccourcir son code, rien de plus. @Nick: Je ne peux pas voir Enums comme une bonne idée de Python, alors n'écrivez pas l'énumé parfaite pour vous, mais vous devez suivre les commentaires de Martineau si vous souhaitez utiliser cela.
@ THC4K: En fait, ce que l'OP a demandé était "Y a-t-il une meilleure façon centrée sur le point de faire ce que je fais)" et dit "(ignorer comment j'atteignons les cas invalides)" sur son code d'échantillon.
Si les énumérums ne sont d'aucune utilité dans Python, c'est étrange comment tant de gens ont ressenti le besoin de mettre en œuvre quelque chose comme eux au fil des ans. Une façon dont je les utilise personnellement est de donner des noms comme des nombres magiques et de rendre mes scripts plus descriptifs et lisibles.
Non seulement c'est étrange combien de personnes ont ressenti le besoin de les mettre en œuvre; Ils ont en quelque sorte fini dans la bibliothèque standard! Clairement, il y a beaucoup d'utilité pour eux.
Je ne sais pas pourquoi @jsbueno commentaire est uplifié ici. C'est la situation et certainement pas cruft. Toujours essayer d'adapter le bon outil pour la bonne situation et méfiez-vous des programmeurs qui soutiennent que la seule façon est la vraie façon.
Utilisez un dict:
MyEnum['VAL4'] = 4
Si je dois construire un 2e dictionnaire pour aller dans l'autre sens, cela viole la valeur de la définition unique préférée dans n'importe quelle langue. Comment répondez-vous à cette préoccupation?
L'extensibilité n'est pas une fonctionnalité pour Enums.
Vous ne devez pas avoir à coder vos valeurs dans la classe - vous feriez mieux d'avoir une usine d'énumérateur. Alors qu'à cela, il suffit d'ajouter des Nicetieurs fournis par Python, par exemple, remplacer la méthode de représentation ou l'attribut GET:
>>> enum = Enumerator("val1", "val2", "val3") >>> enum ['val3', 'val2', 'val1'] >>> enum.val2 1 >>> enum["val1"] 0 >>> enum[2] 'val3'
Cela fera ce que vous voulez et générera votre implémentation légèrement réduisant le code de la plaque de chaudière:
[Time passe ...]
Le nouveau Python Enum a enfin atterri en 3.4, et a Également été rééquilibré . La réponse à votre question est donc maintenant à utiliser cela. :) p>
Exemple: p>
Ce montant de si / sinon indique toujours que c'est une solution incorrecte;)
duplicaillier possible de Quel est le meilleur moyen de mettre en œuvre un "Enum 'en python?
@Nick: Vous voudrez peut-être changer votre réponse acceptée.