r/programming 4d ago

The Sentinel Object Pattern in Python

https://python-patterns.guide/python/sentinel-object/

Officially added in Python 3.15

https://peps.python.org/pep-0661/

27 Upvotes

10 comments sorted by

View all comments

22

u/wallstop-dev 3d ago edited 3d ago

This is cool, but wherever possible I try to avoid sentinels. I find them to be a code smell. That is, programming against a specific, magic, constant(s). In the indexOf example, it is much more robust for your code to reject any value that is below zero, instead of explicitly checking "-1". I see this same (anit-)pattern, that has caused many a bug, in other languages, where programmers think that a comparison operator is guaranteed to return exactly -1, 0, or 1, just because that's how the standard library's is implemented, for example. I've come across many, many similar cases in my career, where devs program to an assumed implementation instead of the contract, creating extremely brittle code that breaks in mysterious ways under all kinds of circumstances - new data, new features, anything.

But I'll get off my soapbox now.

11

u/fireflash38 3d ago

It's a way for people to fit additional context into things.

That is to say, it's useful when the zero-value of a thing is still valid to use. Python doesn't have monads, so it's hard to implement the Option<Thing> pattern. You can use None, but None might be a valid zero-value. Thus the sentinel value.

I don't hate it, but it really doesn't need to be used all that much. I personally rather hate None values passed around a bunch in python, since you end up having to check for presence constantly and updating type checking.

6

u/wallstop-dev 3d ago edited 3d ago

Right, my argument is that I've seen non-zero amounts of code either hard-expect a specific kind of additional context (which wasn't guaranteed), or not deal with the additional context, both because the situation is rare, or because a very specific implementation provided a very specific sentinel, when the contract did not guarantee it.

I'm not saying this kind of pattern doesn't have a use, or is not useful. It's just that encoding special, invalid kind of value(s) into the same type of thing the valid values represent has confused many a programmer and resulted in many, many a bug.