## With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

No credit card required

# Implementing the Null Object Design Pattern

Credit: Dinu C. Gherman

## Problem

You want to reduce the need for conditional statements in your code, particularly the need to keep checking for special cases.

## Solution

The usual marker for “there’s nothing here” is `None`, but we may be able to do better than that:

```class Null:
""" Null objects always and reliably "do nothing." """

def _ _init_ _(self, *args, **kwargs): pass
def _ _call_ _(self, *args, **kwargs): return self
def _ _repr_ _(self): return "Null(  )"
def _ _nonzero_ _(self): return 0

def _ _getattr_ _(self, name): return self
def _ _setattr_ _(self, name, value): return self
def _ _delattr_ _(self, name): return self```

## Discussion

An instance of the `Null` class can replace the primitive value `None`. Using this class, you can avoid many conditional statements in your code and can often express algorithms with little or no checking for special values. This recipe is a sample implementation of the Null Object design pattern (see “The Null Object Pattern”, B. Woolf, Pattern Languages of Programming, PLoP 96, September 1996).

This recipe’s `Null` class ignores all parameters passed when constructing or calling instances and any attempt to set or delete attributes. Any call or attempt to access an attribute (or a method, since Python does not distinguish between the two and calls `_ _getattr_ _` either way) returns the same `Null` instance (i.e., `self`, since there’s no reason to create a new one). For example, if you have a computation such as:

```def compute(x, y):
try: "lots of computation here to return some appropriate object"
except SomeError: return None```

and you use it like this:

```for x in xs:
for y in ys:
obj = compute(x, y)
if obj is not None:
obj.somemethod(y, x)```

you can usefully change the computation to:

```def compute(x, y):
try: "lots of computation here to return some appropriate object"
except SomeError: return Null(  )```

and thus simplify it as:

```for x in xs:
for y in ys:
compute(x, y).somemethod(y, x)```

Thus, you don’t need to check whether `compute` has returned a real result or an instance of `Null`. Even in the latter case, you can safely and innocuously call on it whatever method you want.

Python calls `_ _getattr_ _` for special methods as well. This means that you may have to take some care and customize `Null` to your application’s needs, either directly in the class’s sources or by subclassing it appropriately. For example, with this recipe’s `Null`, any comparison between `Null` instances, even `a==a`, returns a `Null` instance and evaluates as false. (Note that we’ve had to explicitly define `_ _nonzero_ _` for this purpose, since `_ _nonzero_ _` must return an `int`.) If this is a problem for your purposes, you must define `_ _eq_ _` (in `Null` itself or in an appropriate subclass) and implement it appropriately. Similar delicate considerations apply to several other special methods.

The goal of `Null` objects is to provide an intelligent replacement for the often-used primitive value `None` in Python (`Null` or null pointers in other languages). These “nobody lives here” markers are used for many purposes, including the important case in which one member of a group of otherwise similar elements is special. Usually, this usage results in conditional statements to distinguish between ordinary elements and the primitive null (e.g., `None`) value, but `Null` objects help you avoid that.

Among the advantages of using `Null` objects are the following:

• Superfluous conditional statements can be avoided by providing a first-class object alternative for the primitive value `None`, thereby improving code readability.

• They can act as a placeholder for objects whose behavior is not yet implemented.

• They can be used polymorphically with instances of any other class.

• They are very predictable.

To cope with the disadvantage of creating large numbers of passive objects that do nothing but occupy memory space, the Null Object pattern is often combined with the Singleton pattern (see Recipe 5.22), but this recipe does not explore that combination.