Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 661 – 센티널 값

Author:
Tal Einat <tal at python.org>, Jelle Zijlstra <jelle.zijlstra at gmail.com>
Discussions-To:
Discourse thread
Status:
Final
Type:
Standards Track
Created:
06-Jun-2021
Python-Version:
3.15
Post-History:
20-May-2021, 06-Jun-2021
Resolution:
23-Apr-2026

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

Important

This PEP is a historical document. The up-to-date, canonical documentation can now be found at sentinel.

×

See PEP 1 for how to propose changes.

초록

일반적으로 “센티널 값”이라고 알려진 고유한 자리 표시자 값은 프로그래밍에서 흔히 사용됩니다. 다음과 같이 다양하게 사용됩니다:

  • 값이 제공되지 않았을 때 함수 인자의 기본값:
    def foo(value=None):
        ...
    
  • 무언가를 찾을 수 없거나 사용할 수 없을 때 함수가 반환하는 값:
    >>> "abc".find("d")
    -1
    
  • 관계형 데이터베이스의 NULL이나 스프레드시트의 “N/A”(“사용할 수 없음”)와 같은 누락된 데이터

Python에는 특수 값 None이 있으며, 대부분의 경우 이러한 센티널 값으로 사용하도록 의도되었습니다. 그러나 때로는 대체 센티널 값이 필요하며, 일반적으로 해당 맥락에서 None이 유효한 값이므로 None과 구별되어야 할 때 필요합니다. 이러한 사례는 센티널을 구현하기 위한 여러 관용구가 수년에 걸쳐 생겨날 만큼 흔하지만, 표준화가 명확하게 필요하다고 여겨질 만큼 흔하지는 않았습니다. 그러나 표준 라이브러리의 일부를 포함한 일반적인 구현에는 몇 가지 중요한 단점이 있습니다.

이 PEP에서는 센티널 값을 정의하기 위한 내장 클래스를 추가하여 표준 라이브러리에서 사용하고 모든 Python 코드에서 공개적으로 사용할 수 있도록 할 것을 제안합니다. Python에서는 sentinel() 내장 클래스로 센티널을 정의할 수 있고, C에서는 PySentinel_New() C API 함수로 정의할 수 있습니다.

참고: 표준 라이브러리에 기존하는 모든 센티널을 이러한 방식으로 구현하도록 변경할 필요는 없다고 판단하며, 변경 여부는 유지 관리자의 재량에 맡깁니다.

동기

2021년 5월, traceback.print_exception에 사용할 센티널 값을 더 잘 구현하는 방법에 관한 질문이 python-dev 메일링 리스트 [1]에서 제기되었습니다. 기존 구현에서는 다음과 같은 일반적인 관용구를 사용했습니다.:

_sentinel = object()

그러나 이 객체는 정보를 충분히 제공하지 못하고 repr이 지나치게 장황하여 함수 시그니처가 너무 길고 읽기 어렵습니다.:

>>> help(traceback.print_exception)
Help on function print_exception in module traceback:

print_exception(exc, /, value=<object object at
0x000002825DF09650>, tb=<object object at 0x000002825DF09650>,
limit=None, file=None, chain=True)

또한 논의에서는 기존 센티널 중 다수에 해당하는 두 가지 단점이 추가로 제기되었습니다.

  1. 일부는 고유한 타입이 없으므로 이러한 센티널을 기본값으로 사용하는 함수에 대해 명확한 타입 시그니처를 정의할 수 없습니다.
  2. 복사한 후에는 별도의 인스턴스가 생성되므로 예상과 다르게 동작하며, 이에 따라 is를 사용한 비교가 실패합니다. 일부 일반적인 센티널 관용구는 피클링하고 언피클링한 후에도 비슷한 문제를 보입니다.

이어진 논의에서 Victor Stinner은 Python 표준 라이브러리에서 현재 사용 중인 센티널 값 목록 [2] 을 제공했습니다. 이를 통해 센티널의 필요성이 상당히 흔하고, 표준 라이브러리 내부에서도 다양한 구현 방법이 사용되며, 그중 많은 방법이 위의 세 가지 단점 중 적어도 하나를 가진다는 사실이 드러났습니다.

이 논의는 표준 구현 방식이 필요한지 또는 바람직한지, 언급된 단점이 중요한지, 어떤 종류의 구현이 적절한지에 대해 명확한 합의로 이어지지 않았습니다. 이 PEP의 작성자는 개선 방안을 제안하는 이슈를 bugs.python.org에 작성했으며, 현재는 GitHub 이슈 [3] 가 되었지만, 해당 이슈는 몇몇 사례의 문제가 되는 측면 하나에만 초점을 맞췄고 지지를 얻지 못했습니다.

커뮤니티의 의견을 더 명확히 파악하기 위해 discuss.python.org에 설문조사 [4]가 개설되었습니다. 거의 2주가 지나고 상당한 추가 논의와 39표가 있었지만, 설문조사 결과는 결론에 이르지 못했습니다. 40%는 “현 상태는 괜찮다 / 여기에는 일관성이 필요하지 않다”에 투표했지만, 대부분의 투표자는 하나 이상의 표준화된 해결책에 투표했습니다. 구체적으로는 투표자의 37%가 “새로운 전용 센티널 팩토리 / 클래스 / 메타클래스를 일관되게 사용하며, 이를 표준 라이브러리에서 공개적으로 사용할 수 있도록 한다”를 선택했습니다.

이처럼 의견이 엇갈리는 상황에서 이 주제에 대한 결정을 내리는 데 도움이 되도록 이 PEP가 작성되었습니다.

이 PEP를 작성하면서 다양한 선택지와 구현을 반복적으로 검토하고 논의를 계속한 결과, 작성자는 표준 라이브러리 자체와 다른 곳에서 모두 사용할 수 있는 단순하고 훌륭한 구현을 표준 라이브러리에서 제공할 가치가 있다고 생각하게 되었습니다.

근거

선택된 구현을 이끈 기준은 다음과 같습니다:

  1. 센티널 객체는 센티널 객체에 기대되는 대로 동작해야 합니다. 즉, is 연산자로 비교할 때 항상 자기 자신과 동일한 것으로 간주되어야 하지만 다른 어떤 객체와도 동일한 것으로 간주되어서는 안 됩니다.
  2. 센티널 객체를 간단하고 직관적인 한 줄 코드로 생성할 수 있어야 합니다.
  3. 필요한 만큼 서로 다른 센티널 값을 간단하게 정의할 수 있어야 합니다.
  4. 센티널 객체는 명확하고 짧은 repr을 가져야 합니다.
  5. 센티널에 명확한 타입 시그니처를 사용할 수 있어야 합니다.
  6. 센티널 객체는 복사한 후에도 올바르게 동작해야 하며, 피클링하고 피클링 해제할 때 예측 가능한 동작을 보여야 합니다.
  7. 이러한 센티널은 CPython 3.x와 PyPy3에서 작동해야 하며, 이상적으로는 다른 Python 구현에서도 작동해야 합니다.
  8. 구현 측면에서, 특히 사용 측면에서 가능한 한 단순하고 직관적이어야 합니다. Python을 배울 때 이것이 또 하나의 특별한 학습 항목이 되지 않도록 하십시오. 필요할 때 쉽게 찾아 사용할 수 있어야 하며, 코드를 읽을 때 일반적으로 문서를 찾아볼 필요가 없을 만큼 명확해야 합니다.

Python 표준 라이브러리 [2]에서 매우 다양하게 사용되므로 표준 라이브러리에서 사용할 수 있는 구현이 있으면 유용합니다. 표준 라이브러리는 다른 곳에서 제공되는 센티널 객체 구현(예: sentinels [5] 또는 sentinel [6] PyPI 패키지)을 사용할 수 없기 때문입니다.

기존 관용구와 구현을 조사하고 다양한 구현 방식을 검토한 후, API와 구현을 작게 유지하면서 이러한 기준을 충족하도록 아래 설계를 선택했습니다(Reference Implementation 을 참조하십시오).

일반적인 사용 사례를 지원하기 위해 두 가지 사용자 지정 지점을 추가합니다:

  • repr 인자를 사용하여 센티널의 repr()을 사용자 지정할 수 있습니다. 표준 라이브러리의 기존 센티널 중 상당수는 <missing>과 같은 사용자 지정 repr을 사용하며, 이 인자를 사용하면 이러한 동작을 유지하면서 센티널을 새 API로 변환할 수 있습니다.
  • 센티널의 __module__ 특성은 쓰기가 가능하므로, 사용자는 exec()을 통해 생성된 센티널과 같은 일부 특수한 경우에 피클링에 사용되는 모듈을 제어할 수 있습니다. 이는 클래스, 함수, TypeVar 객체 및 (Python 3.15부터) 타입 별칭을 비롯하여 __module__ 특성을 가진 다른 내장 타입의 동작과 일치합니다.

명세

sentinel이라는 이름의 새로운 내장 호출 가능 객체가 추가됩니다.

>>> MISSING = sentinel('MISSING')
>>> MISSING
MISSING

sentinel()은 필수 위치 전용 인자 하나인 name을 받으며, 이 인자는 str이어야 합니다. 또한 선택적인 키워드 전용 인자 repr을 받습니다. name에 문자열이 아닌 값을 전달하면 TypeError가 발생합니다. 이름은 센티널의 이름으로 사용됩니다. repr인자의 값이 지정된 경우 센티널 객체의 str()repr()에 사용됩니다. 지정되지 않으면 대신 이름이 사용됩니다.

센티널 객체에는 두 가지 공개 특성이 있습니다.

  • __name__은 센티널의 이름입니다.
  • __module__sentinel()을 호출한 모듈의 이름입니다. 이 특성은 쓰기가 가능합니다.

sentinel은 서브클래스화할 수 없습니다.

sentinel(name)을 호출할 때마다 새로운 센티널 객체가 반환됩니다. 센티널이 둘 이상의 위치에서 필요하다면 변수에 할당하고 동일한 객체를 명시적으로 재사용해야 합니다. 이는 일반적인 MISSING = object() 관용구와 같습니다.:

MISSING = sentinel('MISSING')

def read_value(default=MISSING):
    ...

그러한 센티널인지 확인하는 작업은 should is 연산자를 사용하여 수행해야 하며, 이는 None에 권장되는 방식입니다. ==를 사용한 동등성 검사는 객체가 자기 자신과 비교될 때만 True를 반환하므로 예상대로 작동합니다. 일반적으로 if value: 또는 if not value:와 같은 부울 검사보다는 if value is MISSING:와 같은 식별성 검사를 사용해야 합니다.

센티널 객체는 “참 같은(truthy)” 객체이므로, 부울 평가 결과는 True가 됩니다. 이는 임의의 클래스에 대한 기본 동작 및 Ellipsis의 부울 값과도 같습니다. 이는 “거짓 같은(falsy)” None과는 다릅니다.

copy.copy() 또는 copy.deepcopy()를 사용하는 등 센티널 객체의 복사본을 만들면 동일한 객체가 반환됩니다.

정의된 모듈에서 이름으로 가져올 수 있는 센티널은 이름이 지정된 싱글턴에 대한 표준 pickle 메커니즘을 사용하여 피클링하고 피클 해제해도 식별성을 유지합니다. sentinel()이 센티널을 생성하면 호출한 모듈을 해당 센티널의 __module__ 속성으로 기록합니다. 피클링은 센티널을 모듈과 이름으로 기록합니다. 피클 해제는 모듈을 가져온 다음 이름으로 센티널을 검색하므로, 다음 왕복 과정에서 식별성이 유지됩니다.:

MISSING = sentinel('MISSING')
assert pickle.loads(pickle.dumps(MISSING)) is MISSING

모듈과 이름으로 가져올 수 없는 센티널은 피클링할 수 없습니다. 예를 들어 로컬 스코프에서 생성되고 이에 대응하는 모듈 전역 또는 클래스 속성에 할당되지 않은 센티널이 이에 해당합니다.

센티널 객체의 repr은 sentinel()에 전달된 name입니다. 암시적인 모듈 한정은 추가되지 않습니다. 한정된 repr이 필요하다면 한정된 이름을 명시적으로 전달해야 합니다.:

>>> MyClass_NotGiven = sentinel('MyClass.NotGiven')
>>> MyClass_NotGiven
MyClass.NotGiven

센티널 객체에 대한 순서 비교는 정의되지 않습니다. 센티널은 weakref를 지원하지 않습니다.

타이핑

타입이 지정된 Python 코드에서 센티널을 명확하고 간단하게 사용할 수 있도록, 센티널 객체에 대한 특별한 경우를 추가하도록 타입 시스템을 수정할 것을 제안합니다.

센티널 객체는 type expressions에서 자기 자신을 나타내는 용도로 사용할 수 있습니다. 이는 기존 타입 시스템에서 None을 처리하는 방식과 유사합니다. 예를 들어 다음과 같습니다.:

MISSING = sentinel('MISSING')

def foo(value: int | MISSING = MISSING) -> int:
    ...

더 형식적으로 말하면, 타입 검사기는 NAME = sentinel('NAME') 형식의 센티널 생성을 새로운 센티널 객체를 생성하는 것으로 인식해야 합니다. sentinel()에 전달된 이름이 객체가 할당된 이름과 일치하지 않으면, 타입 검사기는 오류를 발생시켜야 합니다.

이 구문을 사용하여 정의된 센티널은 type expressions에서 사용할 수 있습니다. 이는 센티널 객체 자체라는 단일 멤버를 가진 fully static type을 나타냅니다.

타입 검사기는 isis not 연산자를 사용하여 센티널이 포함된 유니언 타입의 범위를 좁히는 기능을 지원해야 합니다.:

from typing import assert_type

MISSING = sentinel('MISSING')

def foo(value: int | MISSING) -> None:
    if value is MISSING:
        assert_type(value, MISSING)
    else:
        assert_type(value, int)

타입 표현식에서 사용할 수 있도록, 센티널 객체의 런타임 구현에는 __or____ror__ 메서드가 있어야 하며, 이 메서드는 typing.Union 객체를 반환해야 합니다.

Typing Council은 supports 이 제안의 이 부분을 지지합니다.

C API

센티널은 C 확장에서도 유용하게 사용할 수 있습니다. 두 개의 새로운 C API 함수를 제안합니다:

  • PyObject *PySentinel_New(const char *name, const char *module_name, const char *repr)는 새 센티널 객체를 생성합니다. reprNULL일 수 있으며, 이 경우 센티널의 repr은 이름과 동일합니다.
  • bool PySentinel_Check(PyObject *obj)는 객체가 센티널인지 확인합니다.

C 코드는 ==연산자를 사용하여 객체가 특정 센티널인지 확인할 수 있습니다.

하위 호환성

새 내장 기능을 추가하면 현재 단순한 이름 sentinelNameError를 발생시키는 것에 의존하는 코드가 대신 새 내장 기능을 보게 됩니다. 이는 새 내장 기능에 대한 일반적인 호환성 고려 사항입니다. sentinel이라고 하는 기존 로컬, 전역 및 임포트된 이름은 영향을 받지 않습니다. 이미 sentinel이라는 이름을 사용하는 코드는 새 내장 기능을 사용하도록 수정해야 하며, 내장 이름과의 충돌을 경고하는 린터에서 새로운 린터 오류가 발생할 수 있습니다.

이것을 가르치는 방법

문서 문자열, 라이브러리 문서 및 “What’s New”의 한 섹션을 포함한 새 내장 기능과 특성에 대한 일반적인 유형의 문서로 충분합니다.

보안 영향

이 제안은 보안상 영향을 미치지 않을 것입니다.

참조 구현

참조 구현은 CPython 풀 리퀘스트 [10]로 제공됩니다. 이전 참조 구현은 전용 GitHub 저장소 [7]에서 확인할 수 있습니다. 의도한 동작의 개요는 다음과 같습니다.:

class sentinel:
    """Unique sentinel values."""

    __slots__ = ("__name__", "__module__", "_repr")

    def __init_subclass__(cls):
        raise TypeError("type 'sentinel' is not an acceptable base type")

    def __init__(self, name, /, repr=None):
        if not isinstance(name, str):
            raise TypeError("sentinel name must be a string")
        self.__name__ = name
        self.__module__ = sys._getframemodulename(1)
        self._repr = repr if repr is not None else name

    def __repr__(self):
        return self._repr

    def __reduce__(self):
        return self.__name__

    def __copy__(self):
        return self

    def __deepcopy__(self, memo):
        return self

    def __or__(self, other):
        return typing.Union[self, other]

    def __ror__(self, other):
        return typing.Union[other, self]

exists라는 백포트가 typing-extensions모듈에 존재하지만, 그 동작은 이 PEP의 현재 버전과 정확히 일치하지 않습니다.

거부된 아이디어

NotGiven = object()사용

이는 Rationale 섹션에서 언급한 모든 단점을 가집니다.

MISSING또는 Sentinel과 같은 단일 새 센티널 값을 추가

이러한 값은 여러 장소에서 다양한 용도로 사용될 수 있으므로, 일부 사용 사례에서 이것이 결코 유효한 값이 되지 않을 것이라고 항상 확신할 수는 없습니다. 반면 전용되고 고유한 센티널 값은 잠재적인 예외 상황을 고려할 필요 없이 확신을 가지고 사용할 수 있습니다.

또한 센티널 값이 사용되는 맥락에 맞는 의미 있는 이름과 repr을 제공할 수 있다는 점도 유용합니다.

마지막으로 이는 설문 조사 [4]에서 매우 인기가 없었던 선택지로, 찬성표는 12%에 불과했습니다.

기존 Ellipsis센티널 값 사용

이는 Ellipsis의 원래 의도된 용도가 아니지만, pass를 사용하는 대신 빈 클래스나 함수 블록을 정의하는 데 이를 사용하는 관행이 점점 더 일반화되었습니다.

또한 잠재적인 새 단일 센티널 값과 마찬가지로, Ellipsis는 전용되고 고유한 값과 달리 모든 경우에 확신을 가지고 사용할 수 없습니다.

단일 값 열거형 사용

제안된 관용구는 다음과 같습니다.:

class NotGivenType(Enum):
    NotGiven = 'NotGiven'
NotGiven = NotGivenType.NotGiven

과도한 반복 외에도 repr이 지나치게 깁니다: <NotGivenType.NotGiven: 'NotGiven'>. 코드를 조금 더 많이 작성하고 반복을 더 감수하면 더 짧은 repr을 정의할 수 있습니다.

마지막으로, 이 선택지는 투표 [4]에서 아홉 가지 선택지 중 가장 인기가 낮았으며, 표를 전혀 받지 못한 유일한 선택지였습니다.

센티널 클래스 데코레이터

권장되는 관용구는 다음과 같습니다.:

@sentinel
class NotGivenType: pass
NotGiven = NotGivenType()

이를 통해 데코레이터를 매우 간단하고 명확하게 구현할 수 있지만, 이 관용구는 너무 장황하고 반복적이며 기억하기 어렵습니다.

클래스 객체 사용

클래스는 본질적으로 싱글턴이므로, 클래스를 센티널 값으로 사용하는 것은 타당하며 간단하게 구현할 수 있습니다.

가장 간단한 버전은 다음과 같습니다.:

class NotGiven: pass

명확한 repr을 사용하려면 메타클래스를 사용해야 합니다.:

class NotGiven(metaclass=SentinelMeta): pass

… 또는 클래스 데코레이터를 사용해야 합니다.:

@Sentinel
class NotGiven: pass

이런 방식으로 클래스를 사용하는 것은 일반적이지 않으며 혼란을 일으킬 수 있습니다. 주석이 없으면 코드의 의도를 이해하기 어려울 것입니다. 또한 이러한 센티널이 호출 가능 객체가 되는 것처럼 예상하지 못한 바람직하지 않은 동작을 하게 됩니다.

구현을 제공하지 않고 권장되는 “표준” 관용구를 정의하십시오.

가장 일반적으로 사용되는 기존 관용구에는 상당한 단점이 있습니다. 지금까지 이러한 단점을 피하면서도 명확하고 간결한 관용구는 발견되지 않았습니다.

또한 이 주제에 관한 투표 [4]에서 관용구를 권장하는 선택지들은 인기가 낮았으며, 가장 많은 표를 받은 선택지도 유권자의 25%만이 선택했습니다.

새로운 표준 라이브러리 모듈 사용

초기 초안에서는 새로운 sentinels 또는 sentinellib 모듈에 Sentinel 클래스를 추가할 것을 제안했습니다. 그러나 공개 호출 가능 객체 하나를 위해 새 모듈을 추가하는 것은 불필요하며, 모듈을 사용하면 기존 object() 관용구보다 이 기능의 편의성이 떨어집니다. Steering Council은 또한 이 기능을 내장 기능으로 만들어 적어도 object()만큼 쉽게 사용할 수 있도록 할 것을 특별히 권장했습니다.

sentinels라는 이름을 사용하면 기존에 활발히 사용 중인 PyPI 패키지와 충돌할 수도 있습니다. 다른 모듈 이름도 가능하지만, 이 기능을 내장 기능으로 만들면 이름 지정 문제를 완전히 피할 수 있습니다.

모듈별 센티널 이름 레지스트리 사용

초기 초안에서는 센티널 이름이 각 모듈 내에서 고유하도록 만들 것을 제안했습니다. 이 설계에서는 모듈 이름과 센티널 이름을 키로 삼는 프로세스 전역 레지스트리를 사용하므로, 동일한 모듈에서 sentinel("MISSING")을 반복 호출하면 같은 객체를 반환합니다.

동작이 너무 암시적이기 때문에 이는 거부되었습니다. 공유 센티널이 필요한 코드는 MISSING = object()처럼 하나를 명시적으로 정의하고 이름으로 재사용할 수 있습니다. 로컬 스코프의 코드는 호출이나 반복마다 새로운 센티널을 원할 수도 있으므로, sentinel(name)을 반복 호출하면 서로 다른 객체를 생성하여 object()를 반복 호출하는 것처럼 동작해야 합니다.

레지스트리를 제거하면 구현과 멘탈 모델도 더 단순해집니다. sentinel(name)은 repr이 name인 새롭고 고유한 객체를 생성합니다.

모듈 이름 자동 검색 또는 전달

초기 초안에서는 레지스트리 기반 설계를 지원하기 위한 선택적 module_name 인자를 제안했습니다.

레지스트리가 제거되면 핵심 제안에 공개 module_name 인자는 더 이상 필요하지 않습니다. 구현은 TypeVar 및 이와 유사한 헬퍼가 하는 것처럼 호출한 모듈을 내부적으로 계속 기록하므로, pickle이 가져올 수 있는 센티널을 모듈과 이름으로 직렬화할 수 있습니다. 이 내부 모듈 이름은 센티널의 repr에 영향을 주지 않습니다. 모듈 또는 클래스 이름을 포함하는 repr을 원하는 경우, 단일 name 인자에 이를 명시적으로 포함하면 됩니다. 예를 들면 sentinel("mymodule.MISSING")과 같습니다.

불리언 평가의 사용자 지정 허용

논의에서는 센티널이 명시적으로 참으로 평가되거나, 거짓으로 평가되거나, bool로 변환되지 않도록 허용하는 방안을 고려했습니다. 일부 기존 서드파티 센티널은 공개 API의 일부로 거짓으로 평가되는 동작을 노출하며, 여러 참가자는 불리언 컨텍스트에서 예외를 발생시키는 것이 동일성 검사를 더 효과적으로 강제한다고 주장했습니다.

이 PEP에서는 센티널에 일반 객체의 기본 참 동작을 부여하고 동일성 검사를 권장함으로써 초기 제안을 더 단순하게 유지합니다. 추가되는 API와 타이핑의 복잡성이 감수할 가치가 있다고 판단되면 사용자 지정 불리언 동작을 추후 고려할 수 있습니다.

타입 어노테이션에서 typing.Literal 사용하기

이는 논의에서 여러 사람이 제안했으며, 이 PEP에서 처음 채택한 방식입니다. 그러나 예를 들어 Literal["MISSING"]이 센티널 값 MISSING에 대한 전방 참조가 아니라 문자열 값 "MISSING"을 가리키므로 잠재적인 혼동을 일으킬 수 있다는 지적이 있었습니다. 논의에서는 이름만 사용하는 방안도 자주 제안되었습니다. 이는 None이 정립한 전례와 잘 알려진 패턴을 따르며, 임포트를 요구하지 않고 훨씬 짧다는 장점이 있습니다.

추가 참고 사항

  • 클래스 범위에서 정의되는 센티널의 경우 잠재적인 이름 충돌을 피하거나 한정된 repr이 더 명확해지는 경우, 원하는 한정 이름을 명시적으로 전달해야 합니다. 예를 들면 다음과 같습니다.:
    >>> class MyClass:
    ...    NotGiven = sentinel('MyClass.NotGiven')
    >>> MyClass.NotGiven
    MyClass.NotGiven
    
  • 함수 또는 메서드에서 센티널을 생성하는 것도 허용됩니다. sentinel()을 호출할 때마다 서로 다른 객체가 생성되므로, 로컬 범위에서 생성된 센티널은 해당 범위에서 object()를 호출하여 생성한 객체처럼 동작합니다.
  • NotImplemented의 불리언 값은 True이지만, Python 3.9부터 이를 사용하는 것은 더 이상 권장되지 않습니다(사용하면 사용 중단 경고가 생성됩니다). 이 사용 중단은 bpo-35712 [8]에 설명된 것처럼 NotImplemented에 특유한 문제 때문입니다.
  • 여러 관련 센티널 값을 정의하고 그 사이에 정의된 순서가 있을 수 있게 하려면 대신 Enum이나 이와 유사한 것을 사용해야 합니다.
  • typing-sig 메일링 리스트 [9]에서는 이러한 센티널의 타이핑에 관한 논의가 있었으며, 여러 가지 선택지가 논의되었습니다.

각주