# PEP 661: Sentinel Values

**URL:** <https://discuss.python.org/t/pep-661-sentinel-values/9126>\
**Category:** PEPs\
**Created:** [June 6, 2021, 8:07am UTC](https://discuss.python.org/t/pep-661-sentinel-values/9126 "2021-06-06T08:07:06Z")\
**Posts on this page:** 1\
**Showing post:** 252

<div class="post-metadata">

**Author:** ![HexDecimal](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/hexdecimal/32/28376_2.png) [@HexDecimal](https://discuss.python.org/u/HexDecimal)\
**Post date:** [July 24, 2025, 5:26pm UTC](https://discuss.python.org/t/pep-661-sentinel-values/9126/252 "2025-07-24T17:26:29Z")

</div>

Here’s my implementation of customizable truthiness. Like before this really just reveals to me that customizable truthiness as a feature might be too overly engineered and complex:

> **Sentinel generic boolean return types**
>
> The Sentinel class can have `Generic` with a `TypeVar` holding the return type for ` __bool__ ` with the type being one of `Literal[True] | Literal[False] | Never`. Overloads determine which return type is assigned.
> 
> One thing I’m worried about is if the use of `Generic` here would interfere with type-hinting internally. Otherwise this supports type-hinted conversions to boolean literals without special casing.
> 
> ```python
> from types import NotImplementedType
> from typing import Any, Generic, Literal, Never, TypeVar, overload
> 
> _BoolReturnType = TypeVar("_BoolReturnType")
> 
> class Sentinel(Generic[_BoolReturnType]):
> 
> @overload
> def __new__ (cls, *, bool: NotImplementedType) -> Sentinel[Never]: ...
> @overload
> def __new__ (cls, *, bool: Literal[True]) -> Sentinel[Literal[True]]: ...
> @overload
> def __new__ (cls, *, bool: Literal[False]) -> Sentinel[Literal[False]]: ...
> 
> def __new__ (cls, *, bool: bool | NotImplementedType) -> Sentinel[Any]:
> self = super(). __new__ (cls)
> self._bool = bool
> return self
> 
> def __bool__ (self: Sentinel[_BoolReturnType]) -> _BoolReturnType:
> if self._bool is NotImplemented:
> raise TypeError
> return self._bool
> 
> ```
> 
> [Mypy Playground](https://mypy-play.net/?mypy=latest&python=3.13&flags=strict&gist=5653f5409b6392368592218244257295)
> 
> I’ve used a `bool` keyword-only parameter over `bool_value`, `truthiness`, `is_true`, and others. There’s little ambiguity when the options are `bool=True`, `bool=False`, and `bool=NotImplemented` passed to a Sentinel constructor. It’s also less to type out.
> 
> I use `bool=NotImplemented` as the value which raises an error since it’s more explicit than `bool=None` which might imply that a default value is being used or that None’s truthiness is used. `bool=NotImplemented` sets the ` __bool__ ` return type to `Never` and raises an error when truthiness is tested.
> 
> * * *

The main issue with customizable truthiness is that there are no good examples of using it. Any example I’ve seen or tried to make myself was always too forced.

Sentinel types are not in a vacuum, they are mixed with other types and that will determine what a truth test is actually checking for:

- Sentinel mixed with native sentinels: `None`, `False`, `True`, `Ellipsis`, `NotImplemented`
- Sentinel mixed with number types: `int`, `float`
- Sentinel mixed with various containers: `str`, `list`, `tuple`
- Sentinel mixed with custom classes with default truth behavior (this case is sometimes abused by truth-testing `None`)
- Sentinel mixed with objects with unknown behavior

Many examples of sentinels have falsy connotations but I can’t imagine a truth test being valid for the examples above unless it is being passed to third-party code that is already abusing truthiness (and thus would break with simple cases of passing number or container types as some have already stated). Most of the time one would use a predicate function which will handle expected sentinels in situations where truthiness is theoretically needed.

At this point I’m convinced that the optimal solution is to treat conversions to bool as an accident to be avoided, enforced with the following dunder method:

```py
def __bool__ (self) -> Never:
    raise TypeError

```

---

_[View the full topic](https://discuss.python.org/t/pep-661-sentinel-values/9126)._
