일을 하다보면 숫자로 된 코드값을 이용해 값을 구분하는 경우가 많은데, 숫자 코드값을 이용하면 텍스트로 된 데이터를 숫자 두 자리 정도로 압축하기 때문에 데이터가 줄어들고 쿼리 등에서 이용할 때 오타의 위험도 줄어든다. 하지만 아래의 이유들로 인해 코드값을 직접 소스에 사용하는 것이 싫었다.
이때문에 여러 코드값의 조합은 다른 분이 구현해두신 Enum으로 교체하기로 했다. Enum도 결국은 코드값이 변경되거나 추가되었을 때 관리해주어야 하는 유지보수 대상이기 때문에, 빈번하게 수정된다면 불편할 것 같다. 하지만 자주 수정되는 값이라면 애초에 코드값으로 등록하지도 않겠지..
from enum import Enum
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
>>> print(Color.RED)
Color.RED
기본적으로는 위와 같은 형태로 사용한다.
한 가지 헷갈렸던 건, 구현되어있는 Enum 클래스의 __init__
생성자가 무슨 일을 하는지 명확하게 알 수 없었던 점이다..
class Planet(Enum):
MERCURY = (3.303e+23, 2.4397e6)
VENUS = (4.869e+24, 6.0518e6)
EARTH = (5.976e+24, 6.37814e6)
MARS = (6.421e+23, 3.3972e6)
JUPITER = (1.9e+27, 7.1492e7)
SATURN = (5.688e+26, 6.0268e7)
URANUS = (8.686e+25, 2.5559e7)
NEPTUNE = (1.024e+26, 2.4746e7)
def __init__(self, mass, radius):
self.mass = mass # in kilograms
self.radius = radius # in meters
@property
def surface_gravity(self):
# 중력 상수 (m3 kg-1 s-2)
G = 6.67300E-11
return G * self.mass / (self.radius * self.radius)
이 부분의 설명이 '__new__()
나 __init__()
가 정의되면 열거형 멤버의 값이 해당 메서드로 전달됩니다' 라고 되어있었는데 이 말이 무슨 의미인지 한 번에 와닿지 않았는데, 아래 코드를 보고 이해할 수 있었다.
>>> Planet.EARTH.value
(5.976e+24, 6378140.0)
>>> Planet.EARTH.surface_gravity
9.802652743337129
__init__()
을 정의하면, 정의된 매개변수 순서대로 각 값에 이름이 붙고, 이것을 외부에서 호출하거나 내부 함수를 구현할 때 사용할 수 있다.
from enum import Enum
class Planet(Enum):
MERCURY = (3.303e+23, 2.4397e6)
VENUS = (4.869e+24, 6.0518e6)
EARTH = (5.976e+24, 6.37814e6)
MARS = (6.421e+23, 3.3972e6)
JUPITER = (1.9e+27, 7.1492e7)
SATURN = (5.688e+26, 6.0268e7)
URANUS = (8.686e+25, 2.5559e7)
NEPTUNE = (1.024e+26, 2.4746e7)
def __init__(self, mass):
self.mass = mass # in kilograms
# self.radius = radius # in meters
@property
def surface_gravity(self):
# 중력 상수 (m3 kg-1 s-2)
G = 6.67300E-11
return G * self.mass / (self.radius * self.radius)
TypeErrorTraceback (most recent call last)
<ipython-input-10-0ff37f5b61bf> in <module>
1 from enum import Enum
2
----> 3 class Planet(Enum):
4 MERCURY = (3.303e+23, 2.4397e6)
5 VENUS = (4.869e+24, 6.0518e6)
/usr/local/lib/python3.8/enum.py in __new__(metacls, cls, bases, classdict)
219 enum_member._name_ = member_name
220 enum_member.__objclass__ = enum_class
--> 221 enum_member.__init__(*args)
222 # If another member with the same value was already defined, the
223 # new member becomes an alias to the existing one.
TypeError: __init__() takes 2 positional arguments but 3 were given
__init__()
의 인자 수를 위에 정의된 상수들과 맞춰주지 않으면 위와 같은 에러가 발생한다. 열거형 멤버의 값이 해당 메서드(__init__()
)로 전달된다는 것이 이런 의미였다. 생성자를 만들어주는 경우 정의한 상수들은 모두 __init__()
메서드로 전달되고, 하나하나가 각 값을 속성으로 가진 Planet 클래스의 객체가 된다.