switch not enum python enums

not - ¿Cómo debo emular y/o evitar enum en Python?



python enumerate (6)

El caso de enumeración más común es valores enumerados que forman parte de un patrón de diseño de Estado o Estrategia. Las enumeraciones son estados específicos o estrategias opcionales específicas para ser utilizadas. En este caso, casi siempre son parte de una definición de clase

class DoTheNeedful( object ): ONE_CHOICE = 1 ANOTHER_CHOICE = 2 YET_ANOTHER = 99 def __init__( self, aSelection ): assert aSelection in ( self.ONE_CHOICE, self.ANOTHER_CHOICE, self.YET_ANOTHER ) self.selection= aSelection

Entonces, en un cliente de esta clase.

dtn = DoTheNeeful( DoTheNeeful.ONE_CHOICE )

He estado usando una clase pequeña para emular Enums en algunos proyectos de Python. ¿Hay una mejor manera o esto tiene más sentido para algunas situaciones?

Código de clase aquí:

class Enum(object): ''''''Simple Enum Class Example Usage: >>> codes = Enum(''FOO BAR BAZ'') # codes.BAZ will be 2 and so on ...'''''' def __init__(self, names): for number, name in enumerate(names.split()): setattr(self, name, number)


La forma integrada de hacer enumeraciones es:

(FOO, BAR, BAZ) = range(3)

que funciona bien para juegos pequeños, pero tiene algunos inconvenientes:

  • necesitas contar la cantidad de elementos a mano
  • no puedes saltear valores
  • si agrega un nombre, también necesita actualizar el número de rango

Para una implementación enum completa en python, ver: http://code.activestate.com/recipes/67107/


Lo que veo más a menudo es esto, en el contexto del módulo de nivel superior:

FOO_BAR = ''FOO_BAR'' FOO_BAZ = ''FOO_BAZ'' FOO_QUX = ''FOO_QUX''

...y después...

if something is FOO_BAR: pass # do something here elif something is FOO_BAZ: pass # do something else elif something is FOO_QUX: pass # do something else else: raise Exception(''Invalid value for something'')

Tenga en cuenta que el uso de is lugar de == está tomando un riesgo aquí: asume que las personas están usando your_module.FOO_BAR lugar de la cadena ''FOO_BAR'' (que normalmente será internado de manera que coincida, pero eso ciertamente puede '' No se puede contar), por lo que puede no ser apropiado según el contexto.

Una de las ventajas de hacerlo de esta manera es que al buscar en cualquier lugar donde se almacena una referencia a esa cadena, es obvio de dónde proviene; FOO_BAZ es mucho menos ambiguo que 2 .

Además de eso, la otra cosa que ofende mis sensibilidades Pythonic es que la clase que propones es el uso de split() . ¿Por qué no simplemente pasar una tupla, lista u otro enumerable para empezar?



Empecé con algo que se parece mucho a la respuesta de S.Lott, pero solo sobrecargué ''str'' y ''eq'' (en lugar de toda la clase de objeto) para poder imprimir y comparar el valor de la enumeración.

class enumSeason(): Spring = 0 Summer = 1 Fall = 2 Winter = 3 def __init__(self, Type): self.value = Type def __str__(self): if self.value == enumSeason.Spring: return ''Spring'' if self.value == enumSeason.Summer: return ''Summer'' if self.value == enumSeason.Fall: return ''Fall'' if self.value == enumSeason.Winter: return ''Winter'' def __eq__(self,y): return self.value==y.value

Imprimir (x) arrojará el nombre en lugar del valor y dos valores que contengan Spring serán iguales entre sí.

>>> x = enumSeason(enumSeason.Spring) >>> print(x) Spring >>> y = enumSeason(enumSeason.Spring) >>> x == y True


Hay mucha buena discusión aquí .