241

I have the following enum defined:

from enum import Enum
class D(Enum):
    x = 1
    y = 2

print(D.x)

now the printed value is

D.x

instead, I wanted the enum's value to be print

1

What can be done to achieve this functionality?

codeforester
  • 39,467
  • 16
  • 112
  • 140
Vaibhav Mishra
  • 11,384
  • 12
  • 45
  • 58
  • 1
    I should clarify the access parameters, I know the D.x.value thing, what I want is D.x string conversion to return the value, sorry if question doesn't make the condition clear. – Vaibhav Mishra Jun 30 '14 at 10:15

5 Answers5

400

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
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • When I compare it with a integer value, it returns as object. Ex: `if D.x == 10: ...`. What approach should I take for integers? – alper Apr 24 '20 at 18:49
  • 1
    @alper: exactly the same way; `D.x` is the enum object, `D.x.value` is an integer value. If you must have the enum values act like integers, use the [`IntEnum` type](https://docs.python.org/3/library/enum.html#intenum), where each element is a subclass of `int` and so `IntEnumD.x == 10` would work. – Martijn Pieters Apr 26 '20 at 12:05
  • I have added `def __eq__(self, other): return int(self.value) == other` and `def __int__(self): return int(self.value)` but still I think I have to use `.value` on cases when I don't use comparing – alper Apr 26 '20 at 12:10
  • 1
    @alper: that `__eq__` implementation doesn't work when `other` is another enum value; `D.x == D.y`, where `D.x.value == D.y.value` would be true, would fail for example. It sounds like you want to use `IntEnum` instead of `Enum` there. – Martijn Pieters Apr 26 '20 at 12:30
  • .value is really annoying since it pollutes your code with a bunch of .value. A solution without .value would be great. I am still using Enum by principle (more precisely, class MyEnumClass(str, Enum): ...) but I must admit I prefer the use of a constants class since I can avoid the .value pollution. – Greg7000 Mar 28 '22 at 17:42
  • 1
    @Greg7000: what are you using `.value` *for*? If you have a `...(str, Enum)` enum, your members are already strings so anything that accepts a string can use that directly for most contexts. E.g. `f"The member is: {MyEnumClass.membername}"`, etc. You can always add your own `__str__` method for those contexts that call `.__str__()` (like print()). – Martijn Pieters Mar 30 '22 at 11:18
  • @Martijn Pieters, you are right I was wrong. At some point in time I faced a context where not using .value caused me an issue but this was either invalid or a twisted case. Thx for the remark. – Greg7000 Mar 30 '22 at 14:18
25

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.

Community
  • 1
  • 1
Vaibhav Mishra
  • 11,384
  • 12
  • 45
  • 58
  • 9
    Why the string formatting and `self._value_`? `return str(self.value)` is more straightforward. – Martijn Pieters Jun 30 '14 at 10:18
  • 1
    I just looked at the source and this was how it is implemented, however you are right and `self.value` is cleaner. – Vaibhav Mishra Jun 30 '14 at 10:20
  • 3
    The single-underscore attributes are internal to the generated enum class; better stick to the documented attribute (which happens to be a special descriptor so that you can still use `value` as a name on your enum type). – Martijn Pieters Jun 30 '14 at 10:28
17

If you are going to print value using f-string then you can inherit your enum from both Enum and str. This way you can have both value and name of the object. For instance:

from enum import Enum


class D(str, Enum):
    x = 1
    y = 2

print(D.x)
print(f"{D.x}")

Outputs:

D.x
1

Inheriting just from Enum will always give a full qualified name.

class D(Enum):
    x = 1
    y = 2

print(D.x)
print(f"{D.x}")

Output

D.x
D.x

This is opposite to if you not inherit from anything where you will get value instead of name:

class D:
    x = 1
    y = 2


print(D.x)
print(f"{D.x}")

Output

1
1

That is why inheriting from both str and Enum you are getting both full qualified name and the value.

Vlad Bezden
  • 83,883
  • 25
  • 248
  • 179
  • is this definition of yours equivalent to : `class D(Enum, str): x = 1 y = 2 ` – udit Aug 16 '22 at 10:36
  • 1
    I like this answer the most. But I fail to understand why `print(D.x)` prints `D.x` whereas `print(f"{D.x}")` prints the actual value `1`. @Vlad may I kindly ask you to elaborate a bit more on your answer. Additionally, why does `str(D.x)` also returns `D.x`? Thanks in advance. – gmagno Sep 22 '22 at 19:06
  • @gmagno, I updated the answer. Please take a look. – Vlad Bezden Sep 24 '22 at 12:53
5

In case you want to compare your enum members to Int values, a better way to do it would be to extend IntEnum:

from enum import IntEnum


class D(IntEnum):
    x = 1
    y = 2


print(D.x)

In this way you can compare values of your enum against integers without explicitly calling .value:

>>> D.x == 1
True

For more information you can check this part of the Python docs: Enum comparisons

Julian Espinel
  • 2,586
  • 5
  • 26
  • 20
  • I guess this answer should be the correct solution since the answer of @Martijn Pieters returns the “position value” which happens to be identical with the assign value. If x would be assigned to 5, `D.x` would return 1 anyways and not 5. – Ling Mar 25 '22 at 18:27
4

The most straightforward dunder method to use is _repr_ instead of _str_ since it will also allow you to print it in that way also in lists.

class D(Enum):
  x = 1
  y = 2

  def __repr__(self):
      return self.value

print([D.x,D.y])
>>> [1, 2]