The Sentinel Object pattern uses unique objects to represent special conditions or values—like missing data or the end of a sequence. It helps you clearly distinguish between user input, default values like None
, and control signals.
In Python, it’s sometimes unclear whether None
was explicitly passed to a function or used as a default. This can lead to bugs when None
has multiple meanings. The Sentinel Object pattern solves this by introducing a unique object that stands for a specific condition, making your code clearer and easier to maintain.
Use this pattern when:
None
with multiple meanings.Avoid this pattern if:
None
, False
, or an empty list is clear and sufficient.A sentinel is a unique, standalone object—usually an instance of a small custom class. It doesn’t compare equal to any regular value and is checked using is
rather than ==
. You can define multiple sentinels to represent different special states.
Imagine a party where guests are expected to bring food or drinks. If someone shows up with neither, it signals the party is over. Each role—food, drinks, or no more guests—can be represented by a unique sentinel.
class Sentinel:
def __init__(self, name):
self.name = name
# Create sentinel objects
FOOD = Sentinel("Food")
DRINK = Sentinel("Drink")
END_OF_PARTY = Sentinel("End of Party")
def party_guest(item):
if item is FOOD:
print("This guest brought food.")
elif item is DRINK:
print("This guest brought drinks.")
else:
print("No more guests at the party.")
# Usage
party_guest(FOOD)
party_guest(DRINK)
party_guest(END_OF_PARTY)
In this example, each sentinel represents a different condition. The function checks which sentinel was passed using is
to determine the behavior.
See the full implementation here: Sentinel Object Pattern on GitHub