Reputation: 20222
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 .
Upvotes: 81
Views: 109076
Reputation: 572
I would recommend using an enum. Instead of values of integers, use values of named-tuples with the integer as one of the tuple values. You can add any amount of data to your tuple. Add capital city, language, and population! The the enum and namedTuple work very well together:
from enum import Enum
from collections import namedtuple
Nat = namedtuple('Nat', ['id', 'abbr'])
class Nationality(Enum):
Poland = Nat(0,'PL')
Germany = Nat(1,'DE')
France = Nat(2,'FR')
def __int__(self):
return self.value.id
def __str__(self):
return self.value.abbr
The __int__ and __str__ are really optional, but allow you to use the int() and str() functions to access your id and abbr.
Look at all the functionality you get! The first one is what you wanted.
>>> position_of_enum = int(Nationality.Poland) # here I want to get 0
>>> abbr_of_enum = str(Nationality.Poland) # "PL"
>>> print(position_of_enum,abbr_of_enum)
0 PL
>>> home=Nationality.France
>>> print(home)
FR
>>> print(int(home))
2
>>> print(home.name)
France
>>> print(home.value)
Nat(id=2, abbr='FR')
>>> print(home.value.id)
2
>>> print(home.value.abbr)
FR
Upvotes: 0
Reputation: 303
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
Upvotes: 0
Reputation: 21
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
Upvotes: 2
Reputation: 91
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.
Upvotes: 9
Reputation: 1126
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]
Upvotes: 22
Reputation: 1679
Please use IntEnum
from enum import IntEnum
class loggertype(IntEnum):
Info = 0
Warning = 1
Error = 2
Fatal = 3
int(loggertype.Info)
0
Upvotes: 156
Reputation: 327
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
Upvotes: 3
Reputation: 284562
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)
Upvotes: 14
Reputation: 69021
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.
Upvotes: 44
Reputation: 300
I have seen something like:
PL, FR, DE = range(3)
Wrap it in a class and viola, you have a namespace for the enumeration.
Upvotes: 4
Reputation: 9890
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),
...
}
Upvotes: 5
Reputation: 5505
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.)
Upvotes: 7