Вопрос-Ответ

How can I represent an 'Enum' in Python?

Как я могу представить 'Enum' в Python?

В основном я разработчик C #, но в настоящее время работаю над проектом на Python.

Как я могу представить эквивалент Enum в Python?

Переведено автоматически
Ответ 1

Перечисления были добавлены в Python 3.4, как описано в PEP 435. Он также был перенесен обратно в 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, и 2.4 в pypi.

Для получения более продвинутых методов перечисления попробуйте библиотеку aenum (2.7, 3.3+, тот же автор, что и enum34. Код не совсем совместим между py2 и py3, например, вам понадобится __order__ в python 2).


  • Чтобы использовать enum34, выполните $ pip install enum34

  • Чтобы использовать aenum, выполните $ pip install aenum

Установка enum (без цифр) установит совершенно другую и несовместимую версию.


from enum import Enum     # for enum34, or the stdlib version
# from aenum import Enum # for the aenum version
Animal = Enum('Animal', 'ant bee cat dog')

Animal.ant # returns <Animal.ant: 1>
Animal['ant'] # returns <Animal.ant: 1> (string lookup)
Animal.ant.name # returns 'ant' (inverse lookup)

или что-то подобное:

class Animal(Enum):
ant = 1
bee = 2
cat = 3
dog = 4

В более ранних версиях одним из способов выполнения перечислений является:

def enum(**enums):
return type('Enum', (), enums)

который используется следующим образом:

>>> Numbers = enum(ONE=1, TWO=2, THREE='three')
>>> Numbers.ONE
1
>>> Numbers.TWO
2
>>> Numbers.THREE
'three'

Вы также можете легко поддерживать автоматическое перечисление с помощью чего-то вроде этого:

def enum(*sequential, **named):
enums = dict(zip(sequential, range(len(sequential))), **named)
return type('Enum', (), enums)

и используется следующим образом:

>>> Numbers = enum('ZERO', 'ONE', 'TWO')
>>> Numbers.ZERO
0
>>> Numbers.ONE
1

Поддержка преобразования значений обратно в имена может быть добавлена таким образом:

def enum(*sequential, **named):
enums = dict(zip(sequential, range(len(sequential))), **named)
reverse = dict((value, key) for key, value in enums.iteritems())
enums['reverse_mapping'] = reverse
return type('Enum', (), enums)

Это перезаписывает все, что имеет это имя, но это полезно для отображения ваших перечислений в выходных данных. Это выдаст KeyError если обратного отображения не существует. В первом примере:

>>> Numbers.reverse_mapping['three']
'THREE'

Если вы используете MyPy, другой способ выразить "перечисления" - с помощью typing.Literal.

Например:

from typing import Literal #python >=3.8
from typing_extensions import Literal #python 2.7, 3.4-3.7


Animal = Literal['ant', 'bee', 'cat', 'dog']

def hello_animal(animal: Animal):
print(f"hello {animal}")

hello_animal('rock') # error
hello_animal('bee') # passes

Ответ 2

До PEP 435 в Python не было эквивалента, но вы могли реализовать свой собственный.

Лично мне нравится, когда все просто (я видел несколько ужасно сложных примеров в сети), что-то вроде этого ...

class Animal:
DOG = 1
CAT = 2

x = Animal.DOG

В Python 3.4 (PEP 435) вы можете сделать Enum базовым классом. Это дает вам немного дополнительной функциональности, описанной в PEP . Например, элементы enum отличаются от целых чисел и состоят из name и a value.

from enum import Enum

class Animal(Enum):
DOG = 1
CAT = 2

print(Animal.DOG)
# <Animal.DOG: 1>

print(Animal.DOG.value)
# 1

print(Animal.DOG.name)
# "DOG"

Если вы не хотите вводить значения, используйте следующий ярлык:

class Animal(Enum):
DOG, CAT = range(2)

Enum реализации могут быть преобразованы в списки и являются итеративными. Порядок его элементов соответствует порядку объявления и не имеет ничего общего с их значениями. Например:

class Animal(Enum):
DOG = 1
CAT = 2
COW = 0

list(Animal)
# [<Animal.DOG: 1>, <Animal.CAT: 2>, <Animal.COW: 0>]

[animal.value for animal in Animal]
# [1, 2, 0]

Animal.CAT in Animal
# True
Ответ 3

Вот одна реализация:

class Enum(set):
def __getattr__(self, name):
if name in self:
return name
raise AttributeError

Вот его использование:

Animals = Enum(["DOG", "CAT", "HORSE"])

print(Animals.DOG)
Ответ 4

Если вам нужны числовые значения, вот самый быстрый способ:

dog, cat, rabbit = range(3)

В Python 3.x вы также можете добавить отмеченный звездочкой заполнитель в конце, который впитает все оставшиеся значения диапазона на случай, если вы не возражаете тратить память впустую и не можете считать:

dog, cat, rabbit, horse, *_ = range(100)
python python-3.x