2011-05-19 23 views
6

tengo una nacionalidad enumeración:Convertir enum a int de Python

class Nationality: 
     Poland='PL' 
     Germany='DE' 
     France='FR' 

¿Cómo puedo convertir esto una enumeración a int en esta o en forma similar:

position_of_enum = int(Nationality.Poland) # here I want to get 0 

sé que puedo hacer si tuviera código por:

counter=0 
for member in dir(Nationality): 
    if getattr(Nationality, member) == code: 
     lookFor = member 
     counter += 1 
return counter 

pero no tengo, y de esta forma parece demasiado grande para python. Estoy seguro de que hay algo mucho más simple.

+0

Una clase no es una enumeración. Por lo tanto, no puedes comparar. –

Respuesta

8

Hay formas mejores (y más "pitónicas") de hacer lo que desee.

O bien utilizar una tupla (o lista si necesita ser modificado), donde se conserva el orden:

code_lookup = ('PL', 'DE', 'FR') 
return lookup.index('PL') 

o usar un diccionario lo largo de las líneas de:

code_lookup = {'PL':0, 'FR':2, 'DE':3} 
return code_lookup['PL'] 

El este último es preferible, en mi opinión, ya que es más legible y explícito.

Un namedtuple También podría ser útil, en su caso específico, aunque es algo excesivo:

import collections 
Nationalities = collections.namedtuple('Nationalities', 
             ['Poland', 'France', 'Germany']) 
nat = Nationalities('PL', 'FR', 'DE') 
print nat.Poland 
print nat.index(nat.Germany) 
+0

echas de menos nombres de nacionalidad. Debo tenerlos – user278618

+0

@ user278618 - Los dejé para abreviarlos. La idea era que usarías una tabla de búsqueda de algún tipo en algún lugar de tu clase 'Nacionalidad'. Podrías simplemente sustituir en tus atributos de clase, en lugar de cadenas. –

5

No puede. Python no almacena el orden de los elementos de clase y dir() los devolverá en cualquier orden.

Al ver a partir de su comentario de que realmente no se requiere una correspondencia de cadenas en enteros, debe, de hecho, hacer exactamente eso:

code_lookup = { 
    'PL': ("Poland", 0), 
    'DE': ("Germany", 1), 
    'FR': ("France", 2), 
    ... 
} 
+0

Estoy usando esta enumeración para establecer el valor de select que está en pocos sitios con css e idioma diferentes, y solo la propiedad de valor es la misma en cada sitio. A partir de esta selección, debo seleccionar la nacionalidad, y los valores de las opciones son 0,1,2. Utilizo este casting en C#, así que esto es de lo que tomé esta idea. – user278618

3

¿Por qué no acaba de definir los valores como números en lugar de cadenas:

class Nationality: 
    POLAND = 0 
    GERMANY = 1 
    FRANCE = 2 

Si necesita acceder a los nombres de dos letras, simplemente puede proporcionar una tabla que los correlacione. (O un diccionario que se correlaciona de otra manera, etc.)

3

he visto algo como:

PL, FR, DE = range(3) 

lo envuelve en una clase y Viola , tiene un espacio de nombre para la enumeración.

8

utilizando el enum34 backport o aenum puede crear una especializada Enum:

# using enum34 
from enum import Enum 

class Nationality(Enum): 

    PL = 0, 'Poland' 
    DE = 1, 'Germany' 
    FR = 2, 'France' 

    def __new__(cls, value, name): 
     member = object.__new__(cls) 
     member._value_ = value 
     member.fullname = name 
     return member 

    def __int__(self): 
     return self.value 

y en uso:

>>> print(Nationality.PL) 
Nationality.PL 
>>> print(int(Nationality.PL)) 
0 
>>> print(Nationality.PL.fullname) 
'Poland' 

Lo anterior es más fácilmente escrito usando aenum :

# using aenum 
from aenum import Enum, MultiValue 

class Nationality(Enum): 
    _init_ = 'value fullname' 
    _settings_ = MultiValue 

    PL = 0, 'Poland' 
    DE = 1, 'Germany' 
    FR = 2, 'France' 

    def __int__(self): 
     return self.value 

que tiene la funcionalidad añadida de:

>>> Nationality('Poland') 
<Nationality.PL: 0> 

Disclosure: Soy el autor de la Python stdlib Enum, la enum34 backport, y la biblioteca Advanced Enumeration (aenum).

+0

Funciona muy bien. ¡Muchas gracias! –