2015-08-03 3 views
0

Я хотел бы создать класс Enum в python. Мне нужен также метод get_str(), например:Класс enum в python

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

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

      } 
    return operation_dispatcher[self] 

Но, к сожалению, этот подход не работает. Объекты являются ints, и я получил сообщение об ошибке, что объект «int» не имеет атрибута get_str ... У вас есть идея, как реализовать эту функциональность?

Я пытался сделать что-то вроде:

Operation.get_str (operation_reference), а также 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]() 
+2

Просто, чтобы вы знали: Если вы используете Python 3.4, вы заново изобретать колесо. https://docs.python.org/3/library/enum.html –

+1

См. ['enum34'] (https://pypi.python.org/pypi/enum34) при использовании python 2. – juanchopanza

ответ

0

Я бы рекомендовал для достижения цели используйте метаклассы, чтобы минимизировать код клиента. Поэтому в первую очередь проверка ниже метакласса:

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 

Это просто подменяет __getattribute__ и возвращает экземпляр дочернего класса, используя значения атрибутов в качестве аргумента конструктора. Кроме того, он обновляет исходное значение для того, чтобы не создавать новый экземпляр каждый раз, и к тому, чтобы сделать проверку равенства, используя ссылку объекта

Затем определяют Enum класс вроде этого:

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) 

Это базовый класс реализует equals (==) оператора, для сравнения с использованием значения int и метода __repr__, чтобы вернуть строковое представление вашего перечисления. Так вот вы идете:

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" 
+0

Что делать, если у меня есть словарь с этими перечислениями, и я хотел бы получить значение в соответствии с ключом? F.G. get = dictionary [Operation.START]. Оператор equals не вызывается и python не может найти ключ ... – Konrad

+0

Вы правы, в этом случае вы можете пойти следующим образом: 'dictionary [Operation.START.value]' – bagrat

+0

Вот что я думал, но у меня все еще есть KeyError ... – Konrad

0

Enum s в Python либо:

  • встроено в Питона 3.4
  • доступен как backport для Python 3.3 до Python 2.4
  • доступен в enhanced library, который также включает класс NamedTuple и класс Constant

Используя, что ваш код будет выглядеть следующим образом:

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 
Смежные вопросы