0

I would like to create an Enum class in python. I need also some get_str() method, something like:

class Operation (object):
    START = 0
    STOP = 1
    (...)

    def get_str(self):
        operation_dispatcher = {
             Operation.START: "start", 
             Operation.STOP: "stop",
             (...)

             }
    return operation_dispatcher[self]

But unfortunately that approach doesn't work. The objects are ints and I got error message that 'int' object has no attribute 'get_str'... Do you have any idea how to implement that functionality?

I tried to do something like:

Operation.get_str(operation_reference) as well as operation_reference.get_str()

UPDATE:

class EnumMeta(type):
    def __getattribute__(self, name):
        return self(super(EnumMeta, self).__getattribute__(name))

class Enum(object):
    __metaclass__ = EnumMeta

    def __init__(self, value):
        super(Enum, self).__init__()

        self.value = value[0]
        self.repr = value[1]

    def __eq__(self, other):
        if isinstance(other, Enum):
            return self.value == other.value
        elif isinstance(other, int):
            return self.value == other
        else:
            return object.__eq__(Enum, other)

    def __repr__(self):
        return str(self.repr)

class Operation(Enum):
    START = (0, "start")
    STOP = (1, "stop")
    (...)

operation_dispatcher = {
             Operation.START: start_method, 
             Operation.STOP: stop_method,
             (...) }

# invoking
operation_dispatcher[Operation.START.value]()
Konrad
  • 570
  • 2
  • 9
  • 25

2 Answers2

0

I would recommend to achieve you goal using metaclasses, in order to minimise the client code. So first of all checkout the below metaclass:

class EnumMeta(type):
    def __getattribute__(self, name):
        actual_value = super(EnumMeta, self).__getattribute__(name)
        if isinstance(actual_value, self):
            return actual_value
        else:
            new_value = self(actual_value)
            super(EnumMeta, self).__setattr__(name, new_value)
            return new_value

It simply overrides the __getattribute__ and returns an instance of the child class using the attributes value as the constructor argument. Also it updates the original value, in order not to create a new instance every time, and besides to make equality check using the reference of the object

Then define an Enum class like this:

class Enum(object):
    __metaclass__ = EnumMeta

    def __init__(self, value):
        super(Enum, self).__init__()

        self.value = value[0]
        self.repr = value[1]

    def __repr__(self):
        return str(self.repr)

This base class implements equals (==) operator, to compare using the int value, and __repr__ method, to return the string representation of your enum. So here you go:

class Operation(Enum):
    START = (0, "start")
    STOP = (1, "stop")

>>> Operation.START == Operation.START
True
>>> Operation.START is Operation.START
True
>>> Operation.START == Operation.STOP
False
>>> Operation.START
"start"
>>> repr(Operation.STOP)
"stop"
bagrat
  • 6,350
  • 4
  • 26
  • 47
0

Enums in Python are either:

  • built-in as of Python 3.4
  • available as a backport for Python 3.3 down to Python 2.4
  • available in an enhanced library which also includes a class-based NamedTuple and a Constant class

Using that your code would look like:

from aenum import IntEnum   # or from enum import IntEnum

class Operation(IntEnum):
    START = 0
    STOP = 1

>>> Operation.START
<Operation.START: 0>

>>> Operation['START']
<Operation.START: 0>

>>> Operation(0)
<Operation.START: 0>

>>> Operation.STOP is Operation.STOP
True

>>> list(Operation)
[<Operation.START: 0>, <Operation.STOP: 1>]

>>> Operation.STOP.name
'STOP'

>>> Operation.STOP.value
1
Ethan Furman
  • 52,296
  • 16
  • 127
  • 201