[python] 파이썬에서 ‘Enum’을 어떻게 나타낼 수 있습니까?

저는 주로 C # 개발자이지만 현재 Python 프로젝트를 진행하고 있습니다.

파이썬에서 Enum과 동등한 것을 어떻게 나타낼 수 있습니까?



답변

PEP 435에 설명 된대로 열거 형이 Python 3.4에 추가되었습니다 . 또한 pypi 에서 3.3, 3.2, 3.1, 2.7, 2.6, 2.5 및 2.4백 포트 되었습니다 .

고급 Enum 기술을 사용하려면 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'


답변

PEP 435 이전에는 Python에는 동등한 기능이 없었지만 직접 구현할 수있었습니다.

나 자신, 나는 이것을 간단하게 유지하는 것을 좋아한다.

class Animal:
    DOG = 1
    CAT = 2

x = Animal.DOG

Python 3.4 ( PEP 435 )에서 Enum 을 기본 클래스로 만들 수 있습니다 . 이것은 PEP에 설명 된 약간의 추가 기능을 제공합니다. 예를 들어 열거 형 멤버는 정수와 구별되며 a name와 a 로 구성 value됩니다.

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


답변

다음은 하나의 구현입니다.

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

사용법은 다음과 같습니다.

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

print(Animals.DOG)


답변

숫자 값이 필요한 경우 가장 빠른 방법은 다음과 같습니다.

dog, cat, rabbit = range(3)

Python 3.x에서는 끝에 별표 표시된 자리 표시자를 추가 할 수 있습니다. 메모리를 낭비하지 않고 계산할 수없는 경우 나머지 범위 값을 모두 흡수합니다.

dog, cat, rabbit, horse, *_ = range(100)


답변

당신을위한 최선의 해결책은 당신이 가짜 에서 요구하는 것에 달려 있습니다 enum.

간단한 열거 형 :

다른 항목을 식별하는 이름enum 목록 만 필요한 경우 Mark Harrison 의 솔루션 (위)이 훌륭합니다.

Pen, Pencil, Eraser = range(0, 3)

를 사용하면 시작 값range 을 설정할 수 있습니다 .

Pen, Pencil, Eraser = range(9, 12)

위의 항목 외에도 항목이 일종의 컨테이너 에 속 해야하는 경우 클래스에 포함하십시오.

class Stationery:
    Pen, Pencil, Eraser = range(0, 3)

열거 형 항목을 사용하려면 컨테이너 이름과 항목 이름을 사용해야합니다.

stype = Stationery.Pen

복잡한 열거 형 :

열거 형의 열거 목록이나 열거 형의보다 복잡한 사용의 경우 이러한 솔루션으로는 충분하지 않습니다. Python Cookbook에 게시 된 Python 에서 열거 시뮬레이션을 위한 Will Ware의 레시피를 확인할 수 있습니다. 온라인 버전은 여기에서 구할 수 있습니다 .

더 많은 정보:

PEP 354 : Python의 열거에는 Python의 열거에 대한 흥미로운 제안과 거부 이유가 있습니다.


답변

Java JDK 5 이전에 사용 된 typesafe 열거 형 패턴에는 여러 가지 장점이 있습니다. Alexandru의 답변과 마찬가지로 클래스를 만들고 클래스 수준 필드는 열거 형 값입니다. 그러나 열거 형 값은 작은 정수가 아닌 클래스의 인스턴스입니다. 이것은 열거 형 값이 실수로 작은 정수와 동등하게 비교되지 않는다는 이점이 있습니다. 인쇄 방법을 제어하고, 유용한 경우 임의의 방법을 추가하고 isinstance를 사용하여 어설 션을 만들 수 있습니다.

class Animal:
   def __init__(self, name):
       self.name = name

   def __str__(self):
       return self.name

   def __repr__(self):
       return "<Animal: %s>" % self

Animal.DOG = Animal("dog")
Animal.CAT = Animal("cat")

>>> x = Animal.DOG
>>> x
<Animal: dog>
>>> x == 1
False

python-dev 의 최근 스레드는 다음을 포함하여 야생에 두 개의 열거 형 라이브러리가 있다고 지적했습니다.


답변

Enum 클래스는 하나의 라이너가 될 수 있습니다.

class Enum(tuple): __getattr__ = tuple.index

사용 방법 (정방향 및 역방향 조회, 키, 값, 항목 등)

>>> State = Enum(['Unclaimed', 'Claimed'])
>>> State.Claimed
1
>>> State[1]
'Claimed'
>>> State
('Unclaimed', 'Claimed')
>>> range(len(State))
[0, 1]
>>> [(k, State[k]) for k in range(len(State))]
[(0, 'Unclaimed'), (1, 'Claimed')]
>>> [(k, getattr(State, k)) for k in State]
[('Unclaimed', 0), ('Claimed', 1)]