5

If I have a class like this:

class MyClass:
    ONE = 1
    TWO = 2

Is there a way to simplify the code below using reflection or some other Python feature?

def class_value_to_string(my_class_num):
    if my_class_num == MyClass.ONE:
        return "ONE"
    elif my_class_num == MyClass.TWO:
        return "TWO"
    else:
        return "UNKNOWN VALUE"
Thomas Johnson
  • 10,776
  • 18
  • 60
  • 98
  • I have no idea why this was voted closed. But it highlight a common SO issue, where there may be useful answers somewhere else, but that someone coming from google would certainly never find those answers in their searches, most often caused by SW developers technical jargon. Certainly nobody would google for *`Enum class (with tostring fromstring)`* if they don't even know what those terms are while wanting to do exactly what this title says. I vote to reopen. – not2qubit Dec 25 '20 at 20:34
  • 1
    @not2qubit AFAIK, this closed question would still be visible on searches (tried googling the title). It acts as a signpost to link you to that other Q&A pair with the other answers, since, as you say, people won't be able to find that one if they use a different search string. The purpose of closing as a duplicate is to hopefully maintain just 1 Q&A pair, and then just link the others to it. People coming to this from search, would be linked to the other one. – Gino Mempin Dec 26 '20 at 02:09

2 Answers2

4

You can enumerate the attributes of the class and reverse the lookup:

enum_names = {value: name for name, value in vars(MyClass).items() if name.isupper()}

Using this you can map values back to names.

Demo:

>>> class MyClass:
...     ONE = 1
...     TWO = 2
... 
>>> enum_names = {value: name for name, value in vars(MyClass).items() if name.isupper()}
>>> enum_names[1]
'ONE'
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
1
class MyClass:
    ONE = 1
    TWO = 2
    def func(self):
        return 105

def foo():
    return 204

MyClass.akfoo = foo

def class_value_to_string(my_class_num,the_class):
    try:
        return (k for k,v in the_class.__dict__.iteritems() if v==my_class_num).next()
    except:
        return "UNKNOWN VALUE"

print class_value_to_string(1,MyClass)
print class_value_to_string(2,MyClass)
print class_value_to_string(3,MyClass)
print class_value_to_string(MyClass.func.im_func,MyClass)
print class_value_to_string(foo,MyClass)

result

ONE
TWO
UNKNOWN VALUE
func
akfoo
eyquem
  • 26,771
  • 7
  • 38
  • 46
  • This doesn't work on py3, not even with `import six` or `from future.utils import iteritems`. And trying to use *items()* as replacement, you get `Using AttributeError: 'int' object has no attribute '__dict__` – not2qubit Dec 25 '20 at 21:45