
파이썬 3.15부터는 None과 실제 값의 부재를 구분하는 센티널 sentinel을 내장 기능으로 사용할 수 있다. 센티널은 유효한 값과 겹치지 않는 표시값으로, 캐시에서 키가 없을 때와 값이 None일 때를 구별하거나 설정에서 ‘변경하지 않음’과 ‘값을 지움’을 나눌 때 쓸 수 있다.
None은 값이 없거나 설정되지 않았다는 뜻, 오류 신호, 실제 값 등 여러 의미로 쓰여 혼동을 일으킬 수 있다. 파이썬의 Ellipsis와 NotImplemented, Pydantic의 MISSING도 각각 특정 상황에서 센티널 역할을 한다. Pydantic의 MISSING은 필드에 null이 명시된 경우와 필드 자체가 전달되지 않은 경우를 구분하며, Pydantic 2.14에서 실험 단계를 벗어났다. Pydantic 2.14 릴리스 안내
기존에는 MISSING = object()처럼 직접 센티널을 만들 수 있었지만, 정적 타입 검사기에서 타입을 좁히기 어렵다. TypeIs 가드, Literal 문자열, 단일 멤버 Enum 같은 우회법도 각각 절충점이 있으며, 센티널을 복사하거나 피클링하면 동일성 검사에 문제가 생길 수 있다.
PEP 661은 센티널 표준화를 제안했으며, PyConDE가 열린 4월에는 보류된 상태였지만 9일 뒤 파이썬 운영위원회가 채택했다. 파이썬 3.15부터는 sentinel을 내장 함수로 제공하며, 타입 검사기는 이를 None처럼 타입 좁히기에 활용할 수 있다.
MISSING = sentinel("MISSING")
def update_email(user_id: int, email: str | None | MISSING = MISSING) -> None:
if email is MISSING:
return # nothing to update
elif email is None:
db.delete_email(user_id)
else:
db.set_email(user_id, email.lower()) # narrowed to str
이전 파이썬 버전에서는 typing_extensions의 sentinel 백포트를 사용할 수 있다. 다만 타입 검사기의 지원은 아직 따라오는 중이므로, 사용 전에 해당 검사기의 지원 여부를 확인해야 한다.
기존 object()나 Enum 방식 대신 새 내장 기능을 쓰고, 라이브러리가 제공하는 센티널이 있다면 우선 활용하는 것이 핵심이다. None을 반환해 예외 발생을 대신하려는 경우에는 예외와 결과 타입에 관한 발표 자료도 참고할 수 있다.
PyConDE 발표 슬라이드는 PEP 661이 보류됐다고 적힌 이전 버전이다. 새 sentinel 내장 기능을 다루는 최신 발표 녹화는 EuroPython 세션이다.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요