GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing python-patterns.guide — The Sentinel Object Pattern The Sentinel Object Pattern¶A Python variation on the traditional Sentinel Value pattern Verdict The Sentinel Object pattern is a standard Pythonic approach
that’s used both in the Standard Library and beyond.
The pattern most often uses Python’s built-in Programming is easiest in problem domains where values are always specified: where everyone in the database is guaranteed to have a name, where we know the age of every employee, and where a datum was collected successfully for every second of the experiment. But the world is rarely that simple, and so patterns are needed for those cases where object attributes or whole objects go missing. What simple mechanisms are available to distinguish useful data from placeholders that indicate data is absent? Sentinel Value¶The traditional Sentinel Value pattern
will be familiar to Python programmers
from the
try: i = a.index(b) except: return # versus i = a.find(b) if i == -1: return This is a classic example of a sentinel value.
The value If Sentinel values are particularly common today in the Go language, whose design encourages a programming style that always returns strings instead of mere references to them — forcing the programmer to choose some particular string, like the empty string or a special unique sentinel, to indicate that no data was collected or is present. In Python, the Django framework is famous
for contradicting several decades of database practice
by recommending that you
“Avoid using null on string-based fields” —
with the frequent result that, as in Go,
code becomes simpler;
checks for the empty string replace checks for The Null Pointer Pattern¶The null pointer pattern is impossible in Python,
but worth mentioning to outline the difference between Python
and languages that complicate their data model
with Every name in Python either does not exist,
or exists and refers to an object.
You can remove a name with This guarantee supports an interesting sentinel pattern
down in the default C language implementation of Python.
The C language lacks Python’s guarantee that a name —
which C calls a “pointer” —
will always hold the address of a valid object.
Taking advantage of this flexibility,
C programmers use an address of zero
to mean “this pointer currently doesn’t point at anything” —
which makes zero, or The fact that all Python values, even # Go needs to separately represent “the return value” # and “did this die with an error.” byte_count, err := fmt.Print("Hello, world!") if err != nil { ... } Instead, C language routines that call Python can distinguish legitimate return values from an exception using only the single return value supported by C functions: # The pointer to a Python object instead means # “an exception was raised” if its value is NULL. PyObject *my_repr = PyObject_Repr(obj); if (my_repr == NULL) { ... } The exception itself is stored elsewhere and can be retrieved using the Python C API. The Null Object Pattern¶“Null objects” are real, valid objects that happen to represent a blank value or an item that does not exist. My attention was drawn to this pattern while reading the book Refactoring by Martin Fowler which credits Bobby Woolf for its explication. Note that this pattern has nothing to do with the “null pointer” explained in the previous section! Instead it describes a special kind of sentinel object. Imagine a sequence of A routine tasked with displaying an employee profile
will have to check for the sentinel object for e in employees: if e.manager is None: m = 'no one' else: m = e.manager.display_name() print(e.name, '-', m) And this pattern will need to be repeated everywhere that code touches the manager attribute. Woolf offers the intriguing alternative
of replacing all of the NO_MANAGER = Person(name='no acting manager') Employee objects will now be assigned this
While not appropriate in all situations —
it can, for example, be difficult to design Null Objects
that keep averages and other statistics valid —
Null Objects appear even in the Python Standard Library:
the Sentinel Objects¶Finally we come to the Sentinel Object pattern itself. The standard Python sentinel is the built-in if other_object is None: ... But there are two interesting circumstances
where programs need an alternative to First,
a general purpose data store
doesn’t have the option of using As an example,
the Python Standard Library’s sentinel = object() # unique object used to signal cache misses By providing this sentinel object
as the second argument to result = cache_get(key, sentinel) if result is not sentinel: ... This pattern occurs several times in the Standard Library.
The second interesting circumstance that calls for a sentinel
is when a function or method wants to know
whether a caller supplied an optional keyword argument or not.
Usually Python programmers give such an argument a default of An early description of using sentinels for parameter defaults
was Fredrik Lundh’s
“Default Parameter Values in Python”
which over the years was followed
by posts from Ian Bicking
“The Magic Sentinel”
and Flavio Curella
“Sentinel values in Python”
who both worried about their sentinel objects’ lack of a readable But whatever the application,
the core of the Sentinel Object pattern
is that it is the object’s identity — not its value —
that lets the surrounding code recognize its significance.
If you are using an equality operator to detect the sentinel,
then you are merely using the Sentinel Value pattern
described at the top of this page.
The Sentinel Object is defined
by its use of the Python |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |