_sentinel用作exec的默认参数,函数内部通过它来判断用户有没有指定exc参数。
通常,我们可以把默认参数的值设为None,例如:
def func(foo, bar=None):
print(foo)
if bar is not None:
print(bar)
这个函数的作用是,先打印位置参数foo,然后,如果用户还传递了可选参数bar,接着打印bar。
那怎么判断用户有没有传递bar参数呢?显然,如果函数中bar的值不是None,那么说明用户调用func时一定还传递了bar参数,于是打印bar。
但这个方法有一个问题,那就是无法区分用户是否传递了bar=None作为参数。因为在函数内部看来,用户不传递bar和传递bar=None是没有任何区别的。如果None是有实际语义的,此时显然就不再适合使用None作为bar的默认参数。要解决这个问题,就需要使用上面的_sentinel。我们先创建一个object对象,并赋值给_sentinel:
_sentinel = object()
然后把func函数改成如下形式:
def func(foo, bar=_sentinel):
print(foo)
if bar is not _sentinel:
print(bar)
那么只要bar is not _sentinel成立,用户就一定传递了bar参数,不论他传递的是什么对象。因为is运算符比较的是两个对象的id(也就是内存地址)是否相同,_sentinel对象和其他对象的id必然不同。