说明
《Python 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gr99123(备注:教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
sentinel 是 Python 3.15 新增的一个内置类型,用于创建一个唯一的占位对象(Sentinel Object)。
最典型的用途就是表示:
例如:
MISSING = sentinel("MISSING")
以后就可以写:
def func(value=MISSING):
if value is MISSING:
print("没有传参数")
官方希望用它替代以前大量使用的:
_MISSING = object()
这种写法。
语法非常简单:
sentinel(name, *, repr=None)
参数:
str例如:
MISSING = sentinel("MISSING")
输出:
>>> MISSING
MISSING
如果 name 不是字符串,会抛出 TypeError。
可以使用 repr 参数修改对象的显示形式:
MISSING = sentinel(
"MISSING",
repr="<MISSING>"
)
print(MISSING)
输出:
<MISSING>
如果没有提供 repr,默认使用 name 作为对象的字符串表示。
每调用一次 sentinel(),都会得到一个新的唯一对象。
A = sentinel("A")
B = sentinel("A")
A is B
结果:
False
也就是说:
名称一样,
对象仍然不同。
is 比较官方明确建议:
if value is MISSING:
...
不要写:
value == MISSING
因为 Sentinel 的设计目标是表示唯一身份(Identity),而不是值是否相等。
Sentinel 只等于它自己,推荐始终使用 is / is not 判断。
例如:
bool(MISSING)
结果:
True
因此不能写:
if not value:
去判断 Sentinel。
必须:
if value is MISSING:
官方文档特别说明:Sentinel 对象始终为真值(truthy)。
Sentinel 是一个内置类型。
官方规定:
不支持子类化(Subclassing)。
也就是说不能:
class MySentinel(sentinel):
...
这样做是不允许的。
浅拷贝:
copy.copy(MISSING)
深拷贝:
copy.deepcopy(MISSING)
都会返回:
MISSING
身份保持一致:
copy.copy(MISSING) is MISSING
结果:
True
不会复制出新的 Sentinel。
这是官方特别强调的一点。
只有下面两种 Sentinel 可以 Pickle:
① 模块全局变量
MISSING = sentinel("MISSING")
② 类属性
class Config:
MISSING = sentinel("Config.MISSING")
这样:
pickle.loads(...)
以后:
仍然保持:
is
成立。
但是:
如果是在函数里面创建:
def func():
MISSING = sentinel("MISSING")
这种 Sentinel 不能 Pickle。
这是 Sentinel 最大的价值之一。
官方推荐:
MISSING = sentinel("MISSING")
def next_value(
default: int | MISSING = MISSING
):
...
这里:
int | MISSING
就是合法类型。
这意味着:
参数可能是:
而不是:
Sentinel 支持 | 运算符,因此可以直接参与类型表达式。
类型检查器支持:
if x is MISSING:
自动缩小类型。
例如:
def func(x: int | MISSING):
if x is MISSING:
...
else:
...
那么:
第一分支:
x
类型就是:
MISSING
第二分支:
x
自动变成:
int
这一点在 typing 规范中有明确说明。
每个 Sentinel 都有两个公开属性:
MISSING.__name__
返回:
"MISSING"
还有:
MISSING.__module__
表示创建它的模块名称。
其中:
__module__
是可写的。
官方建议:
MISSING = sentinel("MISSING")
变量名和 Sentinel 名称保持一致。
虽然:
X = sentinel("MISSING")
也是合法的,
但是官方建议两者一致,尤其是在全局作用域,这样不仅可读性更好,也方便类型提示和 Pickle。
一句话概括,sentinel 就是 Python 官方提供的标准哨兵值,用来表示“这是一个特殊占位对象,而不是普通数据”。
它相比以前的 object() 方案,主要有以下优势:
| 特性 | object() |
sentinel() |
|---|---|---|
| 唯一对象 | ✅ | ✅ |
可读的 repr |
❌ | ✅ |
is 身份比较 |
✅ | ✅ |
| 类型提示支持 | ❌ | ✅ |
支持 int \| MISSING |
❌ | ✅ |
| 类型缩小(Type Narrowing) | ❌ | ✅ |
copy / deepcopy 保持身份 |
❌ | ✅ |
| 支持 Pickle(符合条件) | ❌ | ✅ |
__name__、__module__ 属性 |
❌ | ✅ |
因此,在 Python 3.15 及以后,如果你需要表示“未提供值”“缺失值”“特殊标记”,官方推荐直接使用 sentinel(),而不是再手写 MISSING = object()。
更新时间:2026-10-31 23:29:53 标签:python 哨兵 哨兵对象