title: Associating string representations with an Enum that uses integer values?
body: <p>I'm trying to create an enum that has integer values, but which can also return a display-friendly string for each value. I was thinking that I could just define a dict mapping values to strings and then implement <code>__str__</code> and a static constructor with a string argument, but there's a problem with that...</p>
  
  <p>(Under different circumstances I could have just made the underlying data type for this Enum a string rather than an integer, but this is being used as a mapping for an enum database table, so both the integer value and the string are meaningful, the former being a primary key.)</p>
  
  <pre><code>from enum import Enum
  
  class Fingers(Enum):
      THUMB = 1
      INDEX = 2
      MIDDLE = 3
      RING = 4
      PINKY = 5
  
      _display_strings = {
          THUMB: "thumb",
          INDEX: "index",
          MIDDLE: "middle",
          RING: "ring",
          PINKY: "pinky"
          }
  
      def __str__(self):
          return self._display_strings[self.value]
  
      @classmethod
      def from_string(cls, str1):
          for val, str2 in cls._display_strings.items():
              if str1 == str2:
                  return cls(val)
          raise ValueError(cls.__name__ + ' has no value matching "' + str1 + '"')
  </code></pre>
  
  <p>When converting to string, I get the following error:</p>
  
  <pre class="lang-none prettyprint-override"><code>&gt;&gt;&gt; str(Fingers.RING)
  Traceback (most recent call last):
    File "&lt;pyshell#0&gt;", line 1, in &lt;module&gt;
      str(Fingers.RING)
    File "D:/src/Hacks/PythonEnums/fingers1.py", line 19, in __str__
      return self._display_strings[self.value]
  TypeError: 'Fingers' object is not subscriptable
  </code></pre>
  
  <p>It seems that the issue is that an Enum will use all class variables as the enum values, which causes them to return objects of the Enum type, rather than their underlying type.</p>
  
  <p>A few workarounds I can think of include:</p>
  
  <ol>
  <li>Referring to the dict as <code>Fingers._display_strings.value</code>. (However then <code>Fingers.__display_strings</code> becomes a valid enum value!)</li>
  <li>Making the dict a module variable instead of a class variable.</li>
  <li>Duplicating the dict (possibly also breaking it down into a series of <code>if</code> statements) in the <code>__str__</code> and <code>from_string</code> functions.</li>
  <li>Rather than make the dict a class variable, define a static method <code>_get_display_strings</code> to return the dict, so it doesn't become an enum value.</li>
  </ol>
  
  <p>Note that the initial code above and workaround <code>1.</code> uses the underlying integer values as the dict keys. The other options all require that the dict (or <code>if</code> tests) are defined somewhere other than directly in the class itself, and so it must qualify these values with the class name. So you could only use, e.g., <code>Fingers.THUMB</code> to get an enum object, or <code>Fingers.THUMB.value</code> to get the underlying integer value, but not just <code>THUMB</code>. If using the underlying integer value as the dict key, then you must also use it to look up the dict, indexing it with, e.g., <code>[Fingers.THUMB.value]</code> rather than just <code>[Fingers.THUMB]</code>.</p>
  
  <p>So, the question is, what is the best or most Pythonic way to implement a string mapping for an Enum, while preserving an underlying integer value?</p>