¿Cuál es la mejor manera de emular y/o evitar enumeraciones en Python?[duplicar]

StackOverflow https://stackoverflow.com/questions/108523

  •  01-07-2019
  •  | 
  •  

Pregunta

Esta pregunta ya tiene respuesta aquí:

He estado usando una clase pequeña para emular Enums en algunos proyectos de Python.¿Existe una forma mejor o 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)
¿Fue útil?

Solución

Hay mucha buena discusión. aquí.

Otros consejos

Se han propuesto enumeraciones para su inclusión en el lenguaje anteriormente, pero fueron rechazadas (ver http://www.python.org/dev/peps/pep-0354/), aunque existen paquetes que podrías usar en lugar de escribir tu propia implementación:

El caso de enumeración más común son los 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 que se utilizarán.En este caso, casi siempre son parte integrante de alguna 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

Luego, en un cliente de esta clase.

dtn = DoTheNeeful( DoTheNeeful.ONE_CHOICE )

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 en vez de == está tomando un riesgo aquí: supone que la gente está usando your_module.FOO_BAR en lugar de la cuerda 'FOO_BAR' (que lo hará normalmente ser internado de tal manera que is coincidirá, pero ciertamente no se puede contar con eso), por lo que puede no ser apropiado según el contexto.

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

Además de eso, la otra cosa que ofende mi sensibilidad pitónica con respecto a la clase que propones es el uso de split().¿Por qué no simplemente pasar una tupla, una lista u otro enumerable para empezar?

La forma integrada de hacer enumeraciones es:

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

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

  • necesitas contar el número de elementos a mano.
  • no puedes omitir valores
  • Si agrega un nombre, también necesita actualizar el número de rango.

Para obtener una implementación de enumeración completa en Python, consulte:http://code.activestate.com/recipes/67107/

Comencé 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

Print(x) generará 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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top