This functionality is already built in to Enum:
>>> from enum import Enum
>>> class Build(Enum):
... debug = 200
... build = 400
...
>>> Build['debug']
<Build.debug: 200>
The member names are case sensitive, so if user-input is being converted you need to make sure case matches:
an_enum = input('Which type of build?')
build_type = Build[an_enum.lower()]
Answer from Ethan Furman on Stack OverflowThis functionality is already built in to Enum:
>>> from enum import Enum
>>> class Build(Enum):
... debug = 200
... build = 400
...
>>> Build['debug']
<Build.debug: 200>
The member names are case sensitive, so if user-input is being converted you need to make sure case matches:
an_enum = input('Which type of build?')
build_type = Build[an_enum.lower()]
Another alternative (especially useful if your strings don't map 1-1 to your enum cases) is to add a staticmethod to your Enum, e.g.:
class QuestionType(enum.Enum):
MULTI_SELECT = "multi"
SINGLE_SELECT = "single"
@staticmethod
def from_str(label):
if label in ('single', 'singleSelect'):
return QuestionType.SINGLE_SELECT
elif label in ('multi', 'multiSelect'):
return QuestionType.MULTI_SELECT
else:
raise NotImplementedError
Then you can do question_type = QuestionType.from_str('singleSelect')
Why do widely used frameworks in python use strings instead of enums for parameters?
String-based enum in Python - Stack Overflow
python - Getting value of enum on string conversion - Stack Overflow
Find enum value by enum name in string - Python - Stack Overflow
Videos
First that comes to mind is matplotlib. Why are parameters strings? E.g. fig.legend(loc='topleft').
Wouldn't it be much more elegant for enum LegendPlacement.TOPLEFT to exist?
What was their reasoning when they decided "it'll be strings"?
EDIT: So many great answers already! Much to learn from this...
It seems that it is enough to inherit from str class at the same time as Enum:
from enum import Enum
class MyEnum(str, Enum):
state1 = 'state1'
state2 = 'state2'
The tricky part is that the order of classes in the inheritance chain is important as this:
class MyEnum(Enum, str):
state1 = 'state1'
state2 = 'state2'
throws:
TypeError: new enumerations should be created as `EnumName([mixin_type, ...] [data_type,] enum_type)`
With the correct class the following operations on MyEnum are fine:
print('This is the state value: ' + state)
As a side note, it seems that the special inheritance trick is not needed for formatted strings which work even for Enum inheritance only:
msg = f'This is the state value: {state}' # works without inheriting from str
By reading the documentation (i.e., I didn't try it because I use an older version of Python, but I trust the docs), since Python 3.11 you can do the following:
from enum import StrEnum
class Direction(StrEnum):
NORTH = 'north'
SOUTH = 'south'
print(Direction.NORTH)
>>> north
Note that it looks like when subclassing StrEnum, defining the enum fields as single-value tuples will make no difference at all and would also be treated as strings, like so:
class Direction(StrEnum):
NORTH = 'north', # notice the trailing comma
SOUTH = 'south'
Please refer to the docs and the design discussion for further understanding.
If you're running python 3.6+, execute pip install StrEnum, and then you can do the following (confirmed by me):
from strenum import StrEnum
class URL(StrEnum):
GOOGLE = 'www.google.com'
STACKOVERFLOW = 'www.stackoverflow.com'
print(URL.STACKOVERFLOW)
>>> www.stackoverflow.com
You can read more about it here.
Also, this was mentioned in the docs - how to create your own enums based on other classes:
While IntEnum is part of the enum module, it would be very simple to implement independently:
class IntEnum(int, Enum): pass This demonstrates how similar derived enumerations can be defined; for example a StrEnum that mixes in str instead of int.
Some rules:
When subclassing Enum, mix-in types must appear before Enum itself in the sequence of bases, as in the IntEnum example above.
While Enum can have members of any type, once you mix in an additional type, all the members must have values of that type, e.g. int above. This restriction does not apply to mix-ins which only add methods and don’t specify another type.
When another data type is mixed in, the value attribute is not the same as the enum member itself, although it is equivalent and will compare equal.
%-style formatting: %s and %r call the Enum class’s str() and repr() respectively; other codes (such as %i or %h for IntEnum) treat the enum member as its mixed-in type.
Formatted string literals, str.format(), and format() will use the mixed-in type’s format() unless str() or format() is overridden in the subclass, in which case the overridden methods or Enum methods will be used. Use the !s and !r format codes to force usage of the Enum class’s str() and repr() methods.
Source: https://docs.python.org/3/library/enum.html#others
You are printing the enum object. Use the .value attribute if you wanted just to print that:
print(D.x.value)
See the Programmatic access to enumeration members and their attributes section:
If you have an enum member and need its name or value:
>>> >>> member = Color.red >>> member.name 'red' >>> member.value 1
You could add a __str__ method to your enum, if all you wanted was to provide a custom string representation:
class D(Enum):
def __str__(self):
return str(self.value)
x = 1
y = 2
Demo:
>>> from enum import Enum
>>> class D(Enum):
... def __str__(self):
... return str(self.value)
... x = 1
... y = 2
...
>>> D.x
<D.x: 1>
>>> print(D.x)
1
I implemented access using the following
class D(Enum):
x = 1
y = 2
def __str__(self):
return '%s' % self.value
now I can just do
print(D.x) to get 1 as result.
You can also use self.name in case you wanted to print x instead of 1.
[Time passes...]
The new Python Enum has finally landed in 3.4, and has also been backported. So the answer to your question is now to use that. :)
An example:
>>> from enum import Enum
>>> class Modes(Enum) :
... Mode1 = "M1"
... Mode2 = "M2"
... Mode3 = "M3"
...
>>> Modes.Mode1
<Modes.Mode1: 'M1'>
>>> Modes.Mode1.value
'M1'
>>> Modes.Mode1.value
'M1'
>>> Modes['Mode1'] # index/key notation for name lookup
<Modes.Mode1: 'M1'>
>>> Modes('M1') # call notation for value lookup
<Modes.Mode1: 'M1'>
>>> Modes("XXX") # example error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Anaconda3\lib\enum.py", line 291, in __call__
return cls.__new__(cls, value)
File "C:\Anaconda3\lib\enum.py", line 533, in __new__
return cls._missing_(value)
File "C:\Anaconda3\lib\enum.py", line 546, in _missing_
raise ValueError("%r is not a valid %s" % (value, cls.__name__))
ValueError: 'XXX' is not a valid Modes
Well, here is what you asked for:
class MyEnum:
VAL1, VAL2, VAL3 = range(3)
@classmethod
def tostring(cls, val):
for k,v in vars(cls).iteritems():
if v==val:
return k
@classmethod
def fromstring(cls, str):
return getattr(cls, str.upper(), None)
print MyEnum.fromstring('Val1')
print MyEnum.tostring(2)
But I really don't get the point of Enums in Python. It has such a rich type system as well as generators and coroutines to manage states.
I know I've not been using Enums in Python for more than 12 years, maybe you can get rid of them too ;-)