◾️ enum
enum
은 일반적으로 서로 관련이 있는 여러 개의 상수 집합을 정의할 때 사용된다.
enum 클래스 사용 시 인스턴스의 종류를 제한할 수 있어 견고한 프로그램을 구현하는데 많은 도움이 될 수 있다.
▪️ 클래스 타입 정의
간단한 예시로, 프로그래밍 언어(Python,JavaScript,Java)을 나타내는 enum
클래스를 작성해보자.
enum
내장 모듈로부터 불러온 Enum
클래스를 확장하여 Languages
타입을 만들어보자.
from enum import Enum
class Languages(Enum):
PYTHON = 1
JAVASCRIPT = 2
JAVA = 3
enum 타입의 상수 인스턴스는 기본적으로 이름(name
)과 값(value
)을 속성으로 가진다.
>>> Languages.PYTHON
<Languages.PYTHON: 1>
>>> Languages.PYTHON.name
'PYTHON'
>>> Languages.PYTHON.value
1
enum
타입은 순회가 가능하기 때문에 for
문으로 모든 상수를 쉽게 확인할 수 있다.
>>> for language in Languages:
... print(language)
...
Languages.PYTHON
Languages.JAVASCRIPT
Languages.JAVA
▪️ 함수형 타입 정의
자주 쓰이는 방법은 아니지만 Enum
클래스를 확장하는 대신에 일반 함수처럼 호출을 해서 enum
타입을 정의할 수도 있다.
from enum import Enum
Languages = Enum('Languages','PYTHON JAVASCRIPT JAVA')
list(Languages)
▪️ 값 자동 할당
enum
을 사용할 때에 값(value
)이 무엇인지는 크게 중요하지 않은 경우가 있을 수 있다.
이럴 때는 enum
모듈의 auto()
helper 함수를 사용하면, 첫번째 상수에 1, 두번째 상수에 2, 이렇게 1씩 증가시키면서 모든 상수에 유일한 숫자를 값으로 할당시켜준다.
from enum import Enum, auto
class Languages(Enum):
PYTHON = auto()
JAVASCRIPT = auto()
JAVA = auto()
list(Languages)
>>> list(Languages)
[<Languages.PYTHON: 1>, <Languages.JAVASCRIPT: 2>, <Languages.JAVA: 3>]
auto()
함수를 사용하면 기존 상수에 어떤 숫자를 할당했었는지 알아야 할 필요가 없고, 새로운 상수를 추가할 수 있다는 장점이 있다.
뿐만 아니라, Enum
클래스의 _generate_next_value_()
메서드를 오버라이드하면 숫자가 아닌 다른 값으로 자동 할당할 수 있다.
예를 들어, 상수의 이름과 동일한 문자열을 상수의 값으로 자동 할당이 가능하다.
from enum import Enum, auto
class Languages(Enum):
def _generate_next_value_(name,start,count,value):
return name
PYTHON = auto()
JAVASCRIPT = auto()
JAVA = auto()
list(Languages)
>>> list(Languages)
[<Languages.PYTHON: 'PYTHON'>, <Languages.JAVASCRIPT: 'JAVASCRIPT'>, <Languages.JAVA: 'JAVA'>]
▪️ enum mixin
enum 타입을 사용할 때 한 가지 불편할 수 있는 점은 상수의 이름이나 값에 접근할 때 name
이나 value
속성을 사용해야 한다는 점이다.
>>> Languages.PYTHON.name == 'PYTHON'
True
>>> Languages.JAVASCRIPT.name == 'JAVASCRIPT'
True
>>> Languages.JAVA.name == 'JAVA'
True
왜냐하면 모든 상수는 결국 해당 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 Languages(StrEnum):
PYTHON = auto()
JAVASCRIPT = auto()
JAVA = auto()
이제 Languages
타입이 담고 있는 상수는 완벽하게 문자열로 취급하기 때문에 조금 더 편하게 사용이 가능하다.
class Languages(StrEnum):
PYTHON = auto()
JAVASCRIPT = auto()
JAVA = auto()
>>> Languages.PYTHON == 'PYTHON'
True
>>> isinstance(Languages.PYTHON, str)
True
▪️ Enum 확장
Enum
클래스는 다른 일반 클래스처럼 다양하게 확장하여 사용이 가능하다.
from enum import Enum
class Languages(Enum):
PYTHON = ("PYTHON", "Good")
JAVASCRIPT = ("JAVASCRIPT", "Goood")
JAVA = ("JAVA", "Gooood")
def __init__(self,title: str, description: str) -> None:
self.title = title
self.description = description
@classmethod
def get_most_popular(cls):
return cls.PYTHON