The "object sentinel" trick

Here's a neat trick that's pretty useful:

A sentinel value is a special value you can set a variable to. It's special, because it's different from all "legal" values that could be in that variable. So it's used as a signal.

For example:

If you have a variable x, holding an int... except when the number is undefined, maybe because the user never supplied it. Then you can set x to None. In that case, None is being used as a sentinel value.

But sometimes, the nature of your data makes None a "legal" value. What do you do then?

Example: a dictionary.

If your dictionary "mydict" maps strings to ints, you can write "mydict.get('some_key')". That get() method returns the value for that key in the dictionary, or None if that key isn't in there at all.

The problem: maybe None is a value that gets inserted. Like this:

  1. mydict['some_key'] = None

If that happens, and .get() returns None, does that mean the key isn't in there? Or that it's in, but set to None?

You can't tell. So None doesn't work as a sentinel value in this case.

Okay, how about the string "NONE"? So you could write:

  1. val = mydict.get("some_key", "NONE")</p>

get() can take a second argument, which will be the default instead of None. And this works if your dict values are only supposed to be int or None.

But what if strings are legal values? You didn't solve the problem, you just moved it around. And so on, for every built-in Python value you can think of.

Instead, side step this completely, by creating a unique object. Just do this:

  1. MISSING = object()
  2. val = mydict.get(key, MISSING)
  3. # later...
  4. if val is MISSING:
  5. # ...

What you did is use the built-in class called "object" (yes, it's lower case). And you create an instance of it.

That's unique. It has its own identity. Doesn't exist anywhere else. So there is zero chance that it will overlap with anything you might have in that dictionary.

What I like about this lil' example:

It's easy enough to understand quickly. But it brings together several parts of Python in a way that's complex enough to be interesting. Not to mention useful, from time to time.

Because when you learn about Python at a deeper level, the languages changes for you. You can do things you can't ordinarily do.

So keep learning.