문제

나는 주로 C#개발자,그러나 나는 현재 작업에서 프로젝트 파이썬.

나는 어떻게 나타내는 동급의 타입에서는 파이썬?

도움이 되었습니까?

해결책

열거가 추가되었습 Python3.4 로에서 설명 PEP435.그것은 또한 백포트 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, 2.4 에 pypi.

고급 Enum 기술도 aenum 라이브러리 (2.7,3.3+,동일 저자로 enum34.코드가 완벽하게 호환 사이 py2 및 py3,예를 들어,해야 합 __order__ python2).

  • 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'

다른 팁

전 PEP435,Python 지 않았다는 이에 상응하는 하지만 구현할 수 있다.

내 자신,내가 그것을 유지하는 간단(봤어요 일부는 끔찍하게 복잡한 예에 net),무언가가 다음과 같이...

class Animal:
    DOG = 1
    CAT = 2

x = Animal.DOG

Python3.4(PEP435),할 수 있습니다 Enum 기본 클래스입니다.당신은 약간의 추가 기능 설명 PEP.예를 들어,열거 회원은 정수,그리고 그들로 구성된 namevalue.

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)

Python3.x 할 수도 있습니다 추가 주연 자리에서 끝나는 것을 흡수하는 모든 나머지 값의 범위는 경우에 당신은하지 않는 마음을 낭비하는 메모리 셀 수 없습니다:

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

당신을위한 최고의 솔루션에 따라 달라에서 필요로 하는 가짜 enum.

간단한 enum:

필요한 경우 enum 으로만 목록 이름 다른 식별 항목, 이,솔루션 표 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

복잡한 enum:

대한의 긴 목록 열거 또는 더 복잡한 용도의 열거,이러한 솔루션이 충분하지 않습니다.당신이 볼 수있는 조리법에 의해 상품에 대한 시뮬레이션에서 열거 Python 에 게시 파이썬은 요리책.온라인 버전을 사용할 수 있는 .

더 많은 정보:

PEP354:에서 열거 Python 는 재미있는 내용의 제안서에 대한 열거 Python 그리고 왜 그것이 거부되었습니다.

의 특징이 열거한 패턴에 사용되었 Java pre-JDK5 숫자의 이점이 있습니다.많은에서와 같은 스텝과의 응답,당신은 만들기 클래스고 수준의 수준의 필드 값을 열거;그러나,열거 값은 클래스의 인스턴스가 보다 작은 정수입니다.이 는 장점이 당신의 값을 열거하지 않 실수로 동일하게 비교 작은 정수 제어할 수 있습니다 그들이 어떻게 인쇄,추가 임의 방법는 경우 유용하고션을 사용하여 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)]

Python 이 포함되어 있지 않에 해당하는 enum, 고,다른 답변에 대한 아이디어를 구현하는(당신은 또한에 관심이있을 수 있습니다면 을 통해 상위 버전 에서는 파이썬 cookbook).

그러나 상황에서, enum 라는 것입을 위해서는 C,일반적으로 끝나 그냥을 사용하여 간단한 문자열:때문에 방법 개/속성이 구현,(C)파이썬은 최적화하는 작업이 매우 빠르와 짧은 문자열은 어쨌든,그래서 거기지 않을 정말로 어떤 성능 혜택을 사용하여 정수입니다.에 대비하고 오타/는 잘못된 값을 삽입할 수 있는 검사에서 선택한 장소입니다.

ANIMALS = ['cat', 'dog', 'python']

def take_for_a_walk(animal):
    assert animal in ANIMALS
    ...

(나 불이익에 비해서 클래스를 사용은 당신이 더 이상 잃을 것의 이익을 자동 완성)

그래서,동의합니다.자를 적용하지 않습형에서 안전 Python 하지만,자신을 보호하기 위해서는 바보 같은 실수를 합니다.그래서 우리는 무엇을 생각하겠어요?

class Animal(object):
    values = ['Horse','Dog','Cat']

    class __metaclass__(type):
        def __getattr__(self, name):
            return self.values.index(name)

그것은 지역에서 값을 충돌에서 정의를 내 enum.

>>> Animal.Cat
2

다른 편리한 이점:정말 빨리 역전 검색:

def name_of(self, i):
    return self.values[i]

에 2013-05-10,귀도 동의를 받아 PEP435 파이썬 3.4 표준 라이브러리입니다.이것이 의미하는 파이썬 마지막으로는 내부 지원에 대한 열거!

가 제출할 수 있는 파이썬 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, 2.4.그것은에 Pypi 로 enum34.

선언:

>>> from enum import Enum
>>> class Color(Enum):
...     red = 1
...     green = 2
...     blue = 3

표현:

>>> print(Color.red)
Color.red
>>> print(repr(Color.red))
<Color.red: 1>

반복:

>>> for color in Color:
...   print(color)
...
Color.red
Color.green
Color.blue

프로그래밍 방식으로 액세스:

>>> Color(1)
Color.red
>>> Color['blue']
Color.blue

에 대한 더 많은 정보를 참조하십시오 제안서.공식적인 문서는 아마도 곧 따라.

내가 선호를 사용하여 열거를 정의에서는 파이썬다.

class Animal:
  class Dog: pass
  class Cat: pass

x = Animal.Dog

그것은 더 증거를 사용하여 보다 정수지 않기 때문에 걱정이 없는 정수를 고유(예:당신이 말한 경우 개=1 개와 고양이=1 당신 망).

그것은 더 증거보다 문자열을 사용하지 않기 때문에 걱정하는 오타(예:x=="운수시설정비"가 자동으로 실패하지만,x==동물입니다.운수시설정비 는 런타임 예외).

def M_add_class_attribs(attribs):
    def foo(name, bases, dict_):
        for v, k in attribs:
            dict_[k] = v
        return type(name, bases, dict_)
    return foo

def enum(*names):
    class Foo(object):
        __metaclass__ = M_add_class_attribs(enumerate(names))
        def __setattr__(self, name, value):  # this makes it read-only
            raise NotImplementedError
    return Foo()

이를 다음과 같이 사용:

Animal = enum('DOG', 'CAT')
Animal.DOG # returns 0
Animal.CAT # returns 1
Animal.DOG = 2 # raises NotImplementedError

만 하는 경우에는 고유한 기호와 상관하지 않는 값에 대해,이 라인:

__metaclass__ = M_add_class_attribs(enumerate(names))

이:

__metaclass__ = M_add_class_attribs((object(), name) for name in names)

Hmmm...내 생각에 가장 가까운 것 enum 것,사전 정의 중 이와 같은:

months = {
    'January': 1,
    'February': 2,
    ...
}

months = dict(
    January=1,
    February=2,
    ...
)

다음 사용할 수 있는 상징적인 이름에 대한 상수를 다음과 같다:

mymonth = months['January']

다른 옵션과 같은 목록의 튜플,또는 튜플의 튜플지만,사전하는 단 하나 당신에게 제공"상징적인"(일정한 문자열)에 액세스하는 방법 값이 있습니다.

편집:나는 같은 스텝과의 대답이다!

또 다른 매우 간단의 구현을 열거 라이브러리는 모두 지원되며,사용 namedtuple:

from collections import namedtuple

def enum(*keys):
    return namedtuple('Enum', keys)(*keys)

MyEnum = enum('FOO', 'BAR', 'BAZ')

거나,또는

# With sequential number values
def enum(*keys):
    return namedtuple('Enum', keys)(*range(len(keys)))

# From a dict / keyword args
def enum(**kwargs):
    return namedtuple('Enum', kwargs.keys())(*kwargs.values())

다음과 같은 방법 위에는 하위 클래스 set, 이 수 있습니다:

'FOO' in MyEnum
other = MyEnum.FOO
assert other == MyEnum.FOO

그러나 더 많은 유연성을 수 있으므로 다른 키와 값입니다.이

MyEnum.FOO < MyEnum.BAR

행동으로 예상되는 경우 당신은 버전을 사용하는 것을 채우에서 순차적 수 값입니다.

내가 무엇을 사용:

class Enum(object):
    def __init__(self, names, separator=None):
        self.names = names.split(separator)
        for value, name in enumerate(self.names):
            setattr(self, name.upper(), value)
    def tuples(self):
        return tuple(enumerate(self.names))

는 방법을 사용:

>>> state = Enum('draft published retracted')
>>> state.DRAFT
0
>>> state.RETRACTED
2
>>> state.FOO
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
AttributeError: 'Enum' object has no attribute 'FOO'
>>> state.tuples()
((0, 'draft'), (1, 'published'), (2, 'retracted'))

그래서 이게 당신의 정수 상수 같은 상태입니다.게시하고 두 개의 튜플로 사용하는에서 선택 Django 모델입니다.

Python3.4 있을 것이 공식적인 지원에 대한 열거.을 찾을 수 있습 문서와 예제 여기에는 파이썬 3.4 문서 페이지.

열거가 만들어 클래스를 사용하여 구문을 만드는,그들을 쉽 을 읽기 및 쓰기.대체 생성 방법은 설명서 기능적인 API 를 사용합니다.을 정의하는 열거래 열거는 다음과 같다:

from enum import Enum
class Color(Enum):
     red = 1
     green = 2
     blue = 3

davidg 사용하는 것이 좋 dicts.나는 한 단계 더 나아가 세트를 사용:

months = set('January', 'February', ..., 'December')

이제는지 여부를 테스트할 수 있습 값과 일치 하나의 값을 설정한 다음과 같다:

if m in months:

다음과 같 dF,하지만,나는 일반적으로 사용할 문자열 상수의 장소에서 열거.

이것은 최고의 하나의 보았:"첫째 클래스에서 열거형 Python"

http://code.activestate.com/recipes/413486/

그것은 당신을 제공합니다 클래스가 포함한 모든 열거.이 열거에 비교될 수 있는 각각 기타,지만 어떤 특정한 값;사용할 수 없습니다로서 그들이의 정수 값을 사용할 수 있습니다.(저는 처음에이기 때문에 나는 사용하는 C 열거는 정수값으로 설정하셔야 합니다.그러나 사용할 수 없는 경우에는 그것이 정수로 사용할 수 없습니다 그것은 정수로 실수에 의해서 전반적으로 내 생각하는 것이 승리합니다.) 각각의 열거한 값입니다.인쇄할 수 있습니다 열거형,반복할 수 있을 통해 그들을 테스트할 수 있습는 enum 값이"에서"enum.그것은 꽤 완벽하고 매끄럽습니다.

편집(cfi):위 링크를하지 않 Python3 호환됩니다.여기에 내의 포트 enum.py Python3:

def cmp(a,b):
   if a < b: return -1
   if b < a: return 1
   return 0


def Enum(*names):
   ##assert names, "Empty enums are not supported" # <- Don't like empty enums? Uncomment!

   class EnumClass(object):
      __slots__ = names
      def __iter__(self):        return iter(constants)
      def __len__(self):         return len(constants)
      def __getitem__(self, i):  return constants[i]
      def __repr__(self):        return 'Enum' + str(names)
      def __str__(self):         return 'enum ' + str(constants)

   class EnumValue(object):
      __slots__ = ('__value')
      def __init__(self, value): self.__value = value
      Value = property(lambda self: self.__value)
      EnumType = property(lambda self: EnumType)
      def __hash__(self):        return hash(self.__value)
      def __cmp__(self, other):
         # C fans might want to remove the following assertion
         # to make all enums comparable by ordinal value {;))
         assert self.EnumType is other.EnumType, "Only values from the same enum are comparable"
         return cmp(self.__value, other.__value)
      def __lt__(self, other):   return self.__cmp__(other) < 0
      def __eq__(self, other):   return self.__cmp__(other) == 0
      def __invert__(self):      return constants[maximum - self.__value]
      def __nonzero__(self):     return bool(self.__value)
      def __repr__(self):        return str(names[self.__value])

   maximum = len(names) - 1
   constants = [None] * len(names)
   for i, each in enumerate(names):
      val = EnumValue(i)
      setattr(EnumClass, each, val)
      constants[i] = val
   constants = tuple(constants)
   EnumType = EnumClass()
   return EnumType


if __name__ == '__main__':
   print( '\n*** Enum Demo ***')
   print( '--- Days of week ---')
   Days = Enum('Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su')
   print( Days)
   print( Days.Mo)
   print( Days.Fr)
   print( Days.Mo < Days.Fr)
   print( list(Days))
   for each in Days:
      print( 'Day:', each)
   print( '--- Yes/No ---')
   Confirmation = Enum('No', 'Yes')
   answer = Confirmation.No
   print( 'Your answer is not', ~answer)

간단하게:

class Enum(object): 
    def __init__(self, tupleList):
            self.tupleList = tupleList

    def __getattr__(self, name):
            return self.tupleList.index(name)

다음:

DIRECTION = Enum(('UP', 'DOWN', 'LEFT', 'RIGHT'))
DIRECTION.DOWN
1

나는 경우 필요 Enum 등의 목적을 위해,디코딩하는 바이너리 파일 형식입니다.기능 내가 일하고 싶은 간결한 열거는 정의는 능력을 자유롭게 인스턴스를 만들의 열거 중 하나에 의해 정수 값이거나 문자열을 유용한 representation.여기에서 내가 끝났다:

>>> class Enum(int):
...     def __new__(cls, value):
...         if isinstance(value, str):
...             return getattr(cls, value)
...         elif isinstance(value, int):
...             return cls.__index[value]
...     def __str__(self): return self.__name
...     def __repr__(self): return "%s.%s" % (type(self).__name__, self.__name)
...     class __metaclass__(type):
...         def __new__(mcls, name, bases, attrs):
...             attrs['__slots__'] = ['_Enum__name']
...             cls = type.__new__(mcls, name, bases, attrs)
...             cls._Enum__index = _index = {}
...             for base in reversed(bases):
...                 if hasattr(base, '_Enum__index'):
...                     _index.update(base._Enum__index)
...             # create all of the instances of the new class
...             for attr in attrs.keys():
...                 value = attrs[attr]
...                 if isinstance(value, int):
...                     evalue = int.__new__(cls, value)
...                     evalue._Enum__name = attr
...                     _index[value] = evalue
...                     setattr(cls, attr, evalue)
...             return cls
... 

기발한의 예를 사용:

>>> class Citrus(Enum):
...     Lemon = 1
...     Lime = 2
... 
>>> Citrus.Lemon
Citrus.Lemon
>>> 
>>> Citrus(1)
Citrus.Lemon
>>> Citrus(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __new__
KeyError: 5
>>> class Fruit(Citrus):
...     Apple = 3
...     Banana = 4
... 
>>> Fruit.Apple
Fruit.Apple
>>> Fruit.Lemon
Citrus.Lemon
>>> Fruit(1)
Citrus.Lemon
>>> Fruit(3)
Fruit.Apple
>>> "%d %s %r" % ((Fruit.Apple,)*3)
'3 Apple Fruit.Apple'
>>> Fruit(1) is Citrus.Lemon
True

주요 특징:

  • str(), int()repr() 모두 생산하는 가장 유용한 출력이 가능한 각각의 이름 enumartion,그것의 정수 값이 표현을 평가하는 다시 열거에 있습니다.
  • 열거된 반환되는 값에 의해 생성자들은 엄격하게 제한되는 미리 정의된 값 없이 사고로 열거 값입니다.
  • 열거된 값은 싱글;그들은 엄격 비교 is

내가 정말 좋아 알렉 토마스 솔루션(http://stackoverflow.com/a/1695250):

def enum(**enums):
    '''simple constant "enums"'''
    return type('Enum', (object,), enums)

그것은 우아하고 깨끗하게,하지만 그것은 단지를 만드는 함수 클래스와 지정된 특성이 있습니다.

조금 수정하는 기능을,우리는 그것을 얻을 수 있습니다 행동을 좀 더 enumy':

참고:내가 만든 다음 예제를 통해 재현하기 위해 노력하고 행동의 pygtk 의 새로운 스타일'열거'(같은 프로그램.MessageType.경고)

def enum_base(t, **enums):
    '''enums with a base class'''
    T = type('Enum', (t,), {})
    for key,val in enums.items():
        setattr(T, key, T(val))

    return T

이를 만듭니다 열거를 기반으로 지정된 형식입니다.을 제공 할뿐만 아니라 특성 접근과 같은 이전의 기능 동작으로 당신이 기대하는 열거를 존중하는 형식입니다.그것은 또한 상속하는 기본 클래스입니다.

예를 들어,정수 열거형:

>>> Numbers = enum_base(int, ONE=1, TWO=2, THREE=3)
>>> Numbers.ONE
1
>>> x = Numbers.TWO
>>> 10 + x
12
>>> type(Numbers)
<type 'type'>
>>> type(Numbers.ONE)
<class 'Enum'>
>>> isinstance(x, Numbers)
True

또 다른 흥미로운 것으로 할 수 있는 이 방법은 사용자 정의 명확한 행동으로 재정의하는 내장 방법:

def enum_repr(t, **enums):
    '''enums with a base class and repr() output'''
    class Enum(t):
        def __repr__(self):
            return '<enum {0} of type Enum({1})>'.format(self._name, t.__name__)

    for key,val in enums.items():
        i = Enum(val)
        i._name = key
        setattr(Enum, key, i)

    return Enum



>>> Numbers = enum_repr(int, ONE=1, TWO=2, THREE=3)
>>> repr(Numbers.ONE)
'<enum ONE of type Enum(int)>'
>>> str(Numbers.ONE)
'1'
def enum(*sequential, **named):
    enums = dict(zip(sequential, [object() for _ in range(len(sequential))]), **named)
    return type('Enum', (), enums)

이름을 지정하는 경우,그것은 당신의 문제이지만,하지 않을 경우 객체를 만드는 대신 값을 사용하여 이 작업을 수행할 수 있습:

>>> DOG = enum('BARK', 'WALK', 'SIT')
>>> CAT = enum('MEOW', 'WALK', 'SIT')
>>> DOG.WALK == CAT.WALK
False

사용하는 경우 다른 구현 sited 여기서(또는 사용하는 경우 이름 인스턴스에서 나를 들어)해야 합니다 당신이 시도 하지 않 개체를 비교하려면에서 다른 열거.을 위해 여기에이 가능 함정:

>>> DOG = enum('BARK'=1, 'WALK'=2, 'SIT'=3)
>>> CAT = enum('WALK'=1, 'SIT'=2)
>>> pet1_state = DOG.BARK
>>> pet2_state = CAT.WALK
>>> pet1_state == pet2_state
True

이궁!

새로운 표준에서는 파이썬은 PEP435, 그래서 열거스에서 이용할 수 있는 미래전 버전의 Python:

>>> from enum import Enum

그러나 사용하려면 지금 그것을 설치할 수 있습니다 원래의 라이브러리 동기를 부여하는 PEP:

$ pip install flufl.enum

다음 로 사용할 수 있습당의 온라인 가이드:

>>> from flufl.enum import Enum
>>> class Colors(Enum):
...     red = 1
...     green = 2
...     blue = 3
>>> for color in Colors: print color
Colors.red
Colors.green
Colors.blue

이 열거에서 패키지 PyPI 제공하는 강력한 구현에 열거형.이 대답을 언급 PEP354;이것을 거부했지만 구현되었는 제안 http://pypi.python.org/pypi/enum.

사용이 쉽고 우아한:

>>> from enum import Enum
>>> Colors = Enum('red', 'blue', 'green')
>>> shirt_color = Colors.green
>>> shirt_color = Colors[2]
>>> shirt_color > Colors.red
True
>>> shirt_color.index
2
>>> str(shirt_color)
'green'

스텝과의 제안을 사용하는 클래스를 위한 상수 열거형이 아주 잘 작동합니다.

또한 추가 할 서울특별시 종로구 종로의 설정 상수를 조회 읽을 수 있는 문자열 표현입니다.

이 두 가지 목적을 제공합니다:a)그것은 간단한 방법을 제공합 꽤 인 열거하고 b)사전 논리적으로 그룹화하수 상수도록을 테스트할 수 있습니다.

class Animal:    
  TYPE_DOG = 1
  TYPE_CAT = 2

  type2str = {
    TYPE_DOG: "dog",
    TYPE_CAT: "cat"
  }

  def __init__(self, type_):
    assert type_ in self.type2str.keys()
    self._type = type_

  def __repr__(self):
    return "<%s type=%s>" % (
        self.__class__.__name__, self.type2str[self._type].upper())

여기에는 접근이 어떤 다른 특성을 나는 찾아 가치가있다:

  • 할 수 있>고 < 비교 기반으로 순서에 열거되지 않기 위해 어휘
  • 할 수 있는 주소여 항목 이름,시설 또는 인덱스:x.a,x['a']x[0]
  • 지원하는 슬라이스 작업에 다음과 같[:]또는[-1]

그리고 가장 중요한 을 방지 사이의 비교를 왜냐하면 다른 종류의!

http://code.activestate.com/recipes/413486-first-class-enums-in-python.

많은 doctests 여기에 포함된 것을 설명의 다른 이에 대한 접근 방식이다.

def enum(*names):
    """
SYNOPSIS
    Well-behaved enumerated type, easier than creating custom classes

DESCRIPTION
    Create a custom type that implements an enumeration.  Similar in concept
    to a C enum but with some additional capabilities and protections.  See
    http://code.activestate.com/recipes/413486-first-class-enums-in-python/.

PARAMETERS
    names       Ordered list of names.  The order in which names are given
                will be the sort order in the enum type.  Duplicate names
                are not allowed.  Unicode names are mapped to ASCII.

RETURNS
    Object of type enum, with the input names and the enumerated values.

EXAMPLES
    >>> letters = enum('a','e','i','o','u','b','c','y','z')
    >>> letters.a < letters.e
    True

    ## index by property
    >>> letters.a
    a

    ## index by position
    >>> letters[0]
    a

    ## index by name, helpful for bridging string inputs to enum
    >>> letters['a']
    a

    ## sorting by order in the enum() create, not character value
    >>> letters.u < letters.b
    True

    ## normal slicing operations available
    >>> letters[-1]
    z

    ## error since there are not 100 items in enum
    >>> letters[99]
    Traceback (most recent call last):
        ...
    IndexError: tuple index out of range

    ## error since name does not exist in enum
    >>> letters['ggg']
    Traceback (most recent call last):
        ...
    ValueError: tuple.index(x): x not in tuple

    ## enums must be named using valid Python identifiers
    >>> numbers = enum(1,2,3,4)
    Traceback (most recent call last):
        ...
    AssertionError: Enum values must be string or unicode

    >>> a = enum('-a','-b')
    Traceback (most recent call last):
        ...
    TypeError: Error when calling the metaclass bases
        __slots__ must be identifiers

    ## create another enum
    >>> tags = enum('a','b','c')
    >>> tags.a
    a
    >>> letters.a
    a

    ## can't compare values from different enums
    >>> letters.a == tags.a
    Traceback (most recent call last):
        ...
    AssertionError: Only values from the same enum are comparable

    >>> letters.a < tags.a
    Traceback (most recent call last):
        ...
    AssertionError: Only values from the same enum are comparable

    ## can't update enum after create
    >>> letters.a = 'x'
    Traceback (most recent call last):
        ...
    AttributeError: 'EnumClass' object attribute 'a' is read-only

    ## can't update enum after create
    >>> del letters.u
    Traceback (most recent call last):
        ...
    AttributeError: 'EnumClass' object attribute 'u' is read-only

    ## can't have non-unique enum values
    >>> x = enum('a','b','c','a')
    Traceback (most recent call last):
        ...
    AssertionError: Enums must not repeat values

    ## can't have zero enum values
    >>> x = enum()
    Traceback (most recent call last):
        ...
    AssertionError: Empty enums are not supported

    ## can't have enum values that look like special function names
    ## since these could collide and lead to non-obvious errors
    >>> x = enum('a','b','c','__cmp__')
    Traceback (most recent call last):
        ...
    AssertionError: Enum values beginning with __ are not supported

LIMITATIONS
    Enum values of unicode type are not preserved, mapped to ASCII instead.

    """
    ## must have at least one enum value
    assert names, 'Empty enums are not supported'
    ## enum values must be strings
    assert len([i for i in names if not isinstance(i, types.StringTypes) and not \
        isinstance(i, unicode)]) == 0, 'Enum values must be string or unicode'
    ## enum values must not collide with special function names
    assert len([i for i in names if i.startswith("__")]) == 0,\
        'Enum values beginning with __ are not supported'
    ## each enum value must be unique from all others
    assert names == uniquify(names), 'Enums must not repeat values'

    class EnumClass(object):
        """ See parent function for explanation """

        __slots__ = names

        def __iter__(self):
            return iter(constants)

        def __len__(self):
            return len(constants)

        def __getitem__(self, i):
            ## this makes xx['name'] possible
            if isinstance(i, types.StringTypes):
                i = names.index(i)
            ## handles the more normal xx[0]
            return constants[i]

        def __repr__(self):
            return 'enum' + str(names)

        def __str__(self):
            return 'enum ' + str(constants)

        def index(self, i):
            return names.index(i)

    class EnumValue(object):
        """ See parent function for explanation """

        __slots__ = ('__value')

        def __init__(self, value):
            self.__value = value

        value = property(lambda self: self.__value)

        enumtype = property(lambda self: enumtype)

        def __hash__(self):
            return hash(self.__value)

        def __cmp__(self, other):
            assert self.enumtype is other.enumtype, 'Only values from the same enum are comparable'
            return cmp(self.value, other.value)

        def __invert__(self):
            return constants[maximum - self.value]

        def __nonzero__(self):
            ## return bool(self.value)
            ## Original code led to bool(x[0])==False, not correct
            return True

        def __repr__(self):
            return str(names[self.value])

    maximum = len(names) - 1
    constants = [None] * len(names)
    for i, each in enumerate(names):
        val = EnumValue(i)
        setattr(EnumClass, each, val)
        constants[i] = val
    constants = tuple(constants)
    enumtype = EnumClass()
    return enumtype

여기에는 변형에 알렉스 솔루션:

def enum(*args, **kwargs):
    return type('Enum', (), dict((y, x) for x, y in enumerate(args), **kwargs)) 

x = enum('POOH', 'TIGGER', 'EEYORE', 'ROO', 'PIGLET', 'RABBIT', 'OWL')
assert x.POOH == 0
assert x.TIGGER == 1

이 솔루션은 간단한 방법으로 얻기의 클래스에 대한 열거는 정의 목록으로(없기 정수 과제):

enumeration.py:

import new

def create(class_name, names):
    return new.classobj(
        class_name, (object,), dict((y, x) for x, y in enumerate(names))
    )

example.py:

import enumeration

Colors = enumeration.create('Colors', (
    'red',
    'orange',
    'yellow',
    'green',
    'blue',
    'violet',
))

원래 동안 열거 제안 PEP354, 거부되었 년 전,그것이 정상으로 돌아왔습니다어떤 종류의 열거 수입한 것에 추가 3.2 지만,그것은 다시 밀어 3.3 고 다음을 잊어 있습니다.이 PEP435 위에 포함 Python3.4.참조 구현의 응원이 435 flufl.enum.

As of April2013,가 될 것 같다 일반적인 합의 추가해야 하는 표준 라이브러리에서 3.4—만큼 사람들이 무엇에 동의하는 것""뭔가를 해야 합니다.는 어려운 부분입니다.시 시작하는 쓰레드 , 고 반하는 또 다른 스레드에서의 초기 개월 2013.

한편,모든 시간이 제공됩,회전의 새로운 디자인과 구현에 나타나 PyPI,ActiveState,etc., 그래서 만약 당신이 좋아하지 않 FLUFL 디자인을 시도 PyPI 검색.

변형(과 지원을 얻을 enum 값의 이름) 알렉 토마스의 깔끔한 응답:

class EnumBase(type):
    def __init__(self, name, base, fields):
        super(EnumBase, self).__init__(name, base, fields)
        self.__mapping = dict((v, k) for k, v in fields.iteritems())
    def __getitem__(self, val):
        return self.__mapping[val]

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

Numbers = enum(ONE=1, TWO=2, THREE='three')
print Numbers.TWO
print Numbers[Numbers.ONE]
print Numbers[2]
print Numbers['three']
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top