2008-10-13 7 views
17

Solo mirando formas de obtener constantes con nombre en python.¿Existe alguna forma mejor de obtener una serie de constantes (enumeración) en Python?

class constant_list: 
    (A_CONSTANT, B_CONSTANT, C_CONSTANT) = range(3) 

Entonces, por supuesto, se puede hacer referencia a ella de este modo:

constant_list.A_CONSTANT 

supongo que se podría usar un diccionario, el uso de cadenas:

constant_dic = { 
    "A_CONSTANT" : 1, 
    "B_CONSTANT" : 2, 
    "C_CONSTANT" : 3,} 

y se refieren a ella como esto:

constant_dic["A_CONSTANT"] 

Mi pregunta, entonces, es simple. ¿Hay alguna forma mejor de hacer esto? No digo que estos sean inadecuados ni nada, solo curiosidad, ¿algún otro modismo común que me haya perdido?

Gracias de antemano.

+0

Este es un duplicado de (al menos) [esta pregunta] (http://stackoverflow.com/questions/36932/whats-the-best-way-to-implement-an-enum-in-python) y [esta pregunta] (http://stackoverflow.com/questions/108523/how-should-i-best-emulate-andor-avoid-enums-in-python). Realmente me gustaría que la búsqueda SO hiciera un mejor trabajo. –

Respuesta

19

Para 2,3 o después de:

class Enumerate(object): 
    def __init__(self, names): 
    for number, name in enumerate(names.split()): 
     setattr(self, name, number) 

Para usar:

codes = Enumerate('FOO BAR BAZ') 

codes.BAZ será 2 y así sucesivamente.

Si sólo tiene 2.2, preceder a esto con:

from __future__ import generators 

def enumerate(iterable): 
    number = 0 
    for name in iterable: 
    yield number, name 
    number += 1 

(Esto fue tomado de here)

+0

La herencia del objeto parece innecesaria. Pero funciona, y parece bastante elegante. – Bernard

+3

heredas de un objeto para crear una clase de estilo nuevo. – hop

+0

Si quieres dar claves enum que sean cadenas válidas y asociar valor con ellas Animal = Enum ('Animal', {'ant1.0': 1, 'bee': 2}) –

2

Encuentro que la receta de la clase de enumeración (Estado activo, Python Cookbook) es muy efectiva.

Además, tiene una función de búsqueda que es agradable.

Pev

2

una construcción alternativa para constant_dic:

constants = ["A_CONSTANT", "B_CONSTANT", "C_CONSTANT"] 
constant_dic = dict([(c,i) for i, c in enumerate(constants)]) 
1

En Python, las cadenas son inmutables, por lo que son mejores para las constantes que para los números. El mejor enfoque, en mi opinión, es hacer un objeto que mantiene constantes como cadenas:

class Enumeration(object): 
    def __init__(self, possibilities): 
     self.possibilities = set(possibilities.split()) 

    def all(self): 
     return sorted(self.possibilities) 

    def __getattr__(self, name): 
     if name in self.possibilities: 
      return name 
     raise AttributeError("Invalid constant: %s" % name) 

A continuación, puede utilizar de esta manera:

>>> enum = Enumeration("FOO BAR") 
>>> print enum.all() 
['BAR', 'FOO'] 
>>> print enum.FOO 
FOO 
>>> print enum.FOOBAR 
Traceback (most recent call last): 
    File "enum.py", line 17, in <module> 
    print enum.FOOBAR 
    File "enum.py", line 11, in __getattr__ 
    raise AttributeError("Invalid constant: %s" % name) 
AttributeError: Invalid constant: FOOBAR 
+0

Muy bonito. Pero en realidad no es una enumeración en ese momento, ¿verdad? : p – Bernard

+0

Hmm ... cierto :-) Pero ¿por qué necesitarías eNUMERation en Python, de todos modos? – DzinX

+2

Bueno, los números son inmutables también. Simplemente no son autodocumentados ... –

2

Los siguientes actos como un classisc "escrito en stone "C enum - una vez definido, no puedes cambiarlo, solo puedes leer sus valores. Tampoco puedes instanciarlo. Todo lo que tienes que hacer es "importar enum.py" y derivar de la clase Enum.

# this is enum.py 
class EnumException(Exception): 
    pass 

class Enum(object): 
    class __metaclass__(type): 
     def __setattr__(cls, name, value): 
     raise EnumException("Can't set Enum class attribute!") 
     def __delattr__(cls, name): 
     raise EnumException("Can't delete Enum class attribute!") 

    def __init__(self): 
     raise EnumException("Enum cannot be instantiated!") 

Este es el código de prueba:

# this is testenum.py 
from enum import * 

class ExampleEnum(Enum): 
    A=1 
    B=22 
    C=333 

if __name__ == '__main__' : 

    print "ExampleEnum.A |%s|" % ExampleEnum.A 
    print "ExampleEnum.B |%s|" % ExampleEnum.B 
    print "ExampleEnum.C |%s|" % ExampleEnum.C 
    z = ExampleEnum.A 
    if z == ExampleEnum.A: 
     print "z is A" 

    try: 
     ExampleEnum.A = 4 
     print "ExampleEnum.A |%s| FAIL!" % ExampleEnum.A 
    except EnumException: 
     print "Can't change Enum.A (pass...)" 

    try: 
     del ExampleEnum.A 
    except EnumException: 
     print "Can't delete Enum.A (pass...)" 

    try: 
     bad = ExampleEnum() 
    except EnumException: 
     print "Can't instantiate Enum (pass...)" 
2

Este es el mejor que he visto: "Primera Clase enumeraciones en Python"

http://code.activestate.com/recipes/413486/

Es usted un da clase, y la clase contiene todas las enumeraciones. Las enumeraciones se pueden comparar entre sí, pero no tienen ningún valor particular; no puedes usarlos como un valor entero. (He resistido esto al principio porque estoy acostumbrado a C enums, que son valores enteros. Pero si no puedes usarlo como un entero, no puedes usarlo como un número entero por error, así que, en general, creo que es una victoria.) Cada enum es un objeto único. Puede imprimir enumeraciones, puede iterar sobre ellas, puede probar que un valor enum está "en" la enumeración. Es bastante completo y resbaladizo.

Cuestiones relacionadas