Convert enum to int in python
Question:
I have an enum Nationality:
class Nationality:
Poland='PL'
Germany='DE'
France='FR'
How can I convert this some enum to int in this or similar way:
position_of_enum = int(Nationality.Poland) # here I want to get 0
I know that I can do it if I had code by:
counter=0
for member in dir(Nationality):
if getattr(Nationality, member) == code:
lookFor = member
counter += 1
return counter
but I don’t have, and this way looks too big for python. I’m sure that there is something much simpler .
Answers:
You can’t. Python does not store the order of class elements and dir()
will return them in any order.
Seeing from your comment that you really do require a mapping from strings to integers, you should in fact do exactly that:
code_lookup = {
'PL': ("Poland", 0),
'DE': ("Germany", 1),
'FR': ("France", 2),
...
}
Why don’t you just define the values as numbers instead of strings:
class Nationality:
POLAND = 0
GERMANY = 1
FRANCE = 2
If you need to access the two-letter names, you can simply provide a table that maps them. (Or a dictionary that maps the other way, etc.)
There are better (and more “Pythonic”) ways of doing what you want.
Either use a tuple (or list if it needs to be modified), where the order will be preserved:
code_lookup = ('PL', 'DE', 'FR')
return code_lookup.index('PL')
Or use a dictionary along the lines of:
code_lookup = {'PL':0, 'FR':2, 'DE':3}
return code_lookup['PL']
The latter is preferable, in my opinion, as it’s more readable and explicit.
A namedtuple
might also be useful, in your specific case, though it’s probably overkill:
import collections
Nationalities = collections.namedtuple('Nationalities',
['Poland', 'France', 'Germany'])
nat = Nationalities('PL', 'FR', 'DE')
print nat.Poland
print nat.index(nat.Germany)
I have seen something like:
PL, FR, DE = range(3)
Wrap it in a class and viola, you have a namespace for the enumeration.
Using either the enum34
backport or aenum1
you can create a specialized 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
and in use:
>>> print(Nationality.PL)
Nationality.PL
>>> print(int(Nationality.PL))
0
>>> print(Nationality.PL.fullname)
'Poland'
The above is more easily written using aenum
1:
# 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
which has the added functionality of:
>>> Nationality('Poland')
<Nationality.PL: 0>
1 Disclosure: I am the author of the Python stdlib Enum
, the enum34
backport, and the Advanced Enumeration (aenum
) library.
Please use IntEnum
from enum import IntEnum
class loggertype(IntEnum):
Info = 0
Warning = 1
Error = 2
Fatal = 3
int(loggertype.Info)
0
from enum import Enum
class Nationality(Enum):
Poland = 'PL'
Germany = 'DE'
France = 'FR'
@classmethod
def get_index(cls, type):
return list(cls).index(type)
and then:
Nationality.get_index(Nationality.Poland)
0
from enum import Enum
class Phone(Enum):
APPLE = 1 #do not write comma (,)
ANDROID = 2
#as int:
Phone.APPLE.value
Need to access tuple by index if using commas:
class Phone(Enum):
APPLE = 1, # note: there is comma (,)
ANDROID = 2,
#as int:
Phone.APPLE.value[0]
One straightforward way to achieve this:
from enum import Enum
class Nationality(Enum):
Poland= 1, 'PL'
Germany= 2, 'DE'
France= 3, 'FR'
def __int__(self):
return self.value[0]
def __str__(self):
return self.value[1]
# Example use
if __name__ == "__main__":
print(int(Nationality.Poland))
print(Nationality.Poland)
print(int(Nationality.Poland) == 1)
Output:
>>> 1
>>> PL
>>> True
Explanation: You can create your enum with the desired numeration and string representation as you wish and you get the desired functionality by overwriting the respective __int__
and __str__
methods. To my knowledge, this does not break any contracts of enum
and I prefer to keep functionality encapsulated in their respective classes.
class Nationality(Enum):
Poland = 'PL'
Germany = 'DE'
France = 'FR'
@property
def ordinal(self):
return list(self.__class__).index(self)
@classmethod
def get(cls, index):
return list(cls)[index]
and then:
>>> Nationality.Poland.ordinal
0
also
>>> Nationality.get(2)
Nationality.France
This method is something I am using
from enum import Enum
ClientType_DICT = {
"1": 'webapp',
"2": 'application',
"3": 'embedded'
}
ClientType_ENUM: Enum = Enum('ClientType_ENUM', ClientType_DICT)
print(int(ClientType_ENUM('webapp').name))
@app.post("/example")
def login(device_type: ClientType_ENUM):
deviceType = int(device_type.name) # print 1
I have an enum Nationality:
class Nationality:
Poland='PL'
Germany='DE'
France='FR'
How can I convert this some enum to int in this or similar way:
position_of_enum = int(Nationality.Poland) # here I want to get 0
I know that I can do it if I had code by:
counter=0
for member in dir(Nationality):
if getattr(Nationality, member) == code:
lookFor = member
counter += 1
return counter
but I don’t have, and this way looks too big for python. I’m sure that there is something much simpler .
You can’t. Python does not store the order of class elements and dir()
will return them in any order.
Seeing from your comment that you really do require a mapping from strings to integers, you should in fact do exactly that:
code_lookup = {
'PL': ("Poland", 0),
'DE': ("Germany", 1),
'FR': ("France", 2),
...
}
Why don’t you just define the values as numbers instead of strings:
class Nationality:
POLAND = 0
GERMANY = 1
FRANCE = 2
If you need to access the two-letter names, you can simply provide a table that maps them. (Or a dictionary that maps the other way, etc.)
There are better (and more “Pythonic”) ways of doing what you want.
Either use a tuple (or list if it needs to be modified), where the order will be preserved:
code_lookup = ('PL', 'DE', 'FR')
return code_lookup.index('PL')
Or use a dictionary along the lines of:
code_lookup = {'PL':0, 'FR':2, 'DE':3}
return code_lookup['PL']
The latter is preferable, in my opinion, as it’s more readable and explicit.
A namedtuple
might also be useful, in your specific case, though it’s probably overkill:
import collections
Nationalities = collections.namedtuple('Nationalities',
['Poland', 'France', 'Germany'])
nat = Nationalities('PL', 'FR', 'DE')
print nat.Poland
print nat.index(nat.Germany)
I have seen something like:
PL, FR, DE = range(3)
Wrap it in a class and viola, you have a namespace for the enumeration.
Using either the enum34
backport or aenum1
you can create a specialized 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
and in use:
>>> print(Nationality.PL)
Nationality.PL
>>> print(int(Nationality.PL))
0
>>> print(Nationality.PL.fullname)
'Poland'
The above is more easily written using aenum
1:
# 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
which has the added functionality of:
>>> Nationality('Poland')
<Nationality.PL: 0>
1 Disclosure: I am the author of the Python stdlib Enum
, the enum34
backport, and the Advanced Enumeration (aenum
) library.
Please use IntEnum
from enum import IntEnum
class loggertype(IntEnum):
Info = 0
Warning = 1
Error = 2
Fatal = 3
int(loggertype.Info)
0
from enum import Enum
class Nationality(Enum):
Poland = 'PL'
Germany = 'DE'
France = 'FR'
@classmethod
def get_index(cls, type):
return list(cls).index(type)
and then:
Nationality.get_index(Nationality.Poland)
0
from enum import Enum
class Phone(Enum):
APPLE = 1 #do not write comma (,)
ANDROID = 2
#as int:
Phone.APPLE.value
Need to access tuple by index if using commas:
class Phone(Enum):
APPLE = 1, # note: there is comma (,)
ANDROID = 2,
#as int:
Phone.APPLE.value[0]
One straightforward way to achieve this:
from enum import Enum
class Nationality(Enum):
Poland= 1, 'PL'
Germany= 2, 'DE'
France= 3, 'FR'
def __int__(self):
return self.value[0]
def __str__(self):
return self.value[1]
# Example use
if __name__ == "__main__":
print(int(Nationality.Poland))
print(Nationality.Poland)
print(int(Nationality.Poland) == 1)
Output:
>>> 1
>>> PL
>>> True
Explanation: You can create your enum with the desired numeration and string representation as you wish and you get the desired functionality by overwriting the respective __int__
and __str__
methods. To my knowledge, this does not break any contracts of enum
and I prefer to keep functionality encapsulated in their respective classes.
class Nationality(Enum):
Poland = 'PL'
Germany = 'DE'
France = 'FR'
@property
def ordinal(self):
return list(self.__class__).index(self)
@classmethod
def get(cls, index):
return list(cls)[index]
and then:
>>> Nationality.Poland.ordinal
0
also
>>> Nationality.get(2)
Nationality.France
This method is something I am using
from enum import Enum
ClientType_DICT = {
"1": 'webapp',
"2": 'application',
"3": 'embedded'
}
ClientType_ENUM: Enum = Enum('ClientType_ENUM', ClientType_DICT)
print(int(ClientType_ENUM('webapp').name))
@app.post("/example")
def login(device_type: ClientType_ENUM):
deviceType = int(device_type.name) # print 1