Logo

파이썬 enum 타입 사용법

파이썬은 버전 3.4부터 다른 언어들 처럼 enum(enumeration, 이넘) 타입을 지원하고 있습니다. enum은 일반적으로 서로 관련이 있는 여러 개의 상수의 집합을 정의할 때 사용되는데요. enum 클래스를 사용하면 인스턴스의 종류를 제한할 수 있기 때문에 견고한 프로그램을 작성하는데 도움이 됩니다.

클래스 타입 정의

간단한 예로, 웹에서 사용되는 대표적인 3개의 기술(HTML, CSS, JS)을 나타내는 enum 클래스를 작성해보겠습니다. enum 내장 모듈로 부터 불러온 Enum 클래스를 확장하여 Skill 타입을 만들었습니다.

from enum import Enum

class Skill(Enum):
    HTML = 1
    CSS = 2
    JS = 3

enum 타입의 상수 인스턴스는 기본적으로 이름(name)과 값(value)을 속성을 가집니다.

>>> Skill.HTML
<Skill.HTML: 'HTML'>
>>> Skill.HTML.name
'HTML'
>>> Skill.HTML.value
1

enum 타입은 순회가 가능하기 때문에 for 문으로 모든 상수를 쉽게 확인할 수 있습니다.

>>> for skill in Skill:
...     print(skill)
...
Skill.HTML
Skill.CSS
Skill.JS

함수형 타입 정의

자주 쓰이는 방법은 아니지만 Enum 클래스를 확장하는 대신에 일반 함수처럼 호출을 해서 enum 타입을 정의할 수도 있습니다.

>>> Skill = Enum("Skill", "HTML CSS JS")
>>> list(Skill)
[<Skill.HTML: 1>, <Skill.CSS: 2>, <Skill.JS: 3>]

값 자동 할당

enum을 사용할 때, 많은 경우 값(value)이 무언인지는 크게 중요하지 않습니다. 이럴 때는 enum 모듈의 auto() helper 함수를 사용하면, 첫번째 상수에 1, 두번째 상수에 2, 이렇게 1씩 증가시키면서 모든 상수에 유일한 숫자를 값으로 할당해줍니다.

from enum import Enum, auto

class Skill(Enum):
    HTML = auto()
    CSS = auto()
    JS = auto()
>>> list(Skill)
[<Skill.HTML: 1>, <Skill.CSS: 2>, <Skill.JS: 3>]

auto() 함수를 사용하면 기존 상수에 어떤 숫자가 할당해놨었는지 구애 받지 않고 새로운 상수를 추가할 수 있는 장점도 있습니다.

뿐만 아니라, Enum 클래스의 _generate_next_value_() 메서드를 오버라이드(override)하면 숫자가 아닌 다른 값을 자동 할당할 수 있습니다. 예를 들어, 상수의 이름과 동일한 문자열을 상수의 값으로 자동 할당할 수 있습니다.

from enum import Enum, auto

class Skill(Enum):
    def _generate_next_value_(name, start, count, last_values):
        return name

    HTML = auto()
    CSS = auto()
    JS = auto()
>>> list(Skill)
[<Skill.HTML: 'HTML'>, <Skill.CSS: 'CSS'>, <Skill.JS: 'JS'>]

enum mixin

enum 타입을 사용할 때 한 가지 불편할 수 있는 점은 상수의 이름이나 값에 접근할 때 name이나 value 속성을 사용해야 한다는 것입니다.

>>> Skill.HTML.name == 'HTML'
True
>>> Skill.HTML.value == 1
True
>>> Skill.HTML == 'HTML'
False
>>> type(Skill.HTML)
<enum 'Skill'>

왜냐하면 모든 상수는 결국 해당 enum 타입의 인스턴스이기 때문입니다. 하지만 enum 타입을 사용해서 코딩을 하다보면, 매번 name이나 value를 사용하는 것이 귀찮고 까먹기도 싶습니다.

이럴 때는 enum mixin(믹스인) 기법을 활용하여 str을 확장하는 enum 클래스를 작성합니다.

class StrEnum(str, Enum):
    def _generate_next_value_(name, start, count, last_values):
        return name

    def __repr__(self):
        return self.name

    def __str__(self):
        return self.name

그 다음, 이 클래스를 확장하여 enum 클래스를 정의하면 됩니다.

class Skill(StrEnum):
    HTML = auto()
    CSS = auto()
    JS = auto()

이제 Skill 타입이 담고 있는 상수는 완벽하게 문자열로 취급기 때문에 좀 더 편하게 사용할 수 있습니다.

>>> Skill.HTML == 'HTML'
True
>>> isinstance(Skill.HTML, str)
True

Enum 확장

Enum 클래스는 다른 일반 클래스처럼 다양하게 확장해서 활용할 수 있습니다.

from enum import Enum

class Skill(Enum):
    HTML = ("HTML", "Hypertext Markup Language")
    CSS = ("CSS", "Cascading Style Sheets")
    JS = ("JS", "JavaScript")

    def __init__(self, title, description):
        self.title = title
        self.description = description

    @classmethod
    def get_most_popular(cls):
        return cls.JS

    def lower_title(self):
        return self.title.lower()
>>> Skill.HTML.value
('HTML', 'Hypertext Markup Language')
>>> Skill.HTML.title
'HTML'
>>> Skill.HTML.description
'Hypertext Markup Language'
>>> Skill.get_most_popular()
<Skill.JS: ('JS', 'JavaScript')>
>>> Skill.CSS.lower_title()
'css'

마치면서

이상으로 파이썬에서 enum 내장 모듈을 이용해서 enum 타입을 정의하고 사용하는 방법에 대해서 알아보았습니다. 파이썬의 enum 내장 모듈에 대한 자세한 내용은 아래 파이썬 공식 레퍼런스를 참고 바랍니다.