python typing Literal
Python typing.Literal 정리
Python 코드를 보다가 typing.Literal이라는 타입을 발견해서 정리해봤다.
Literal이란?
Literal은 특정 값만 허용하도록 타입을 제한할 때 사용하는 타입 힌트다.
일반적으로 문자열 타입을 지정할 때는 다음과 같이 작성한다.
def set_mode(mode: str):
print(mode)
하지만 이렇게 작성하면 mode에 어떤 문자열이든 전달할 수 있다.
set_mode("train")
set_mode("test")
set_mode("hello")
만약 "train"과 "test"만 사용하도록 표현하고 싶다면 Literal을 사용할 수 있다.
from typing import Literal
def set_mode(mode: Literal["train", "test"]):
print(mode)
이제 타입 검사기에서는 다음과 같이 판단한다.
set_mode("train") # OK
set_mode("test") # OK
set_mode("hello") # Type Error
즉,
str
이 **"문자열을 받는다"**는 의미라면,
Literal["train", "test"]
은 **"train 또는 test만 받는다"**는 의미다.
타입 별칭으로 사용하기
여러 곳에서 사용한다면 타입 별칭으로 만들어 사용할 수도 있다.
from typing import Literal
HttpMethod = Literal["GET", "POST", "PUT", "DELETE"]
def request(url: str, method: HttpMethod):
print(method, url)
이렇게 작성하면 함수 정의만 봐도 어떤 값이 들어올 수 있는지 쉽게 알 수 있다.
IDE의 자동완성이나 mypy, pyright 같은 정적 타입 검사 도구의 도움도 받을 수 있다.
Literal은 런타임 검증이 아니다
한 가지 주의할 점은 Literal이 실제로 값의 입력을 막아주는 기능은 아니라는 것이다.
from typing import Literal
def set_mode(mode: Literal["train", "test"]):
print(mode)
set_mode("hello")
위 코드는 Python에서 실행된다.
Literal은 어디까지나 타입 힌트이기 때문이다.
실행 중에 잘못된 값까지 막으려면 별도의 검증이 필요하다.
def set_mode(mode: str):
if mode not in ("train", "test"):
raise ValueError("지원하지 않는 mode입니다.")
print(mode)
Literal vs Enum
비슷한 역할을 하는 Enum도 있다.
from enum import Enum
class Mode(Enum):
TRAIN = "train"
TEST = "test"
둘 다 정해진 선택지를 표현할 수 있지만 용도가 조금 다르다.
Literal: 기존 문자열이나 숫자를 그대로 사용하면서 허용되는 값을 타입으로 제한하고 싶을 때Enum: 값에 이름과 의미를 부여하고 하나의 타입으로 관리하고 싶을 때
간단한 함수 옵션이나 몇 개의 문자열 값을 제한하는 정도라면 Literal을 편하게 사용할 수 있다.
정리
Literal의 핵심은 간단하다.
from typing import Literal
Mode = Literal["train", "test"]
str이 **"문자열이어야 한다"**를 나타낸다면, Literal은 **"지정된 값 중 하나여야 한다"**를 나타낸다.
다만 Literal은 런타임 검증 기능이 아니라 타입 힌트라는 점은 기억해두자.
API의 HTTP Method, 실행 모드, 상태값처럼 선택 가능한 값이 정해져 있을 때 유용하게 사용할 수 있다.