Skip to main content
travisci PyPI Package latest release Supported versions Supported implementations Wheel packaging support Test line coverage Test branch coverage

Helps define ‘null’ values and sentinels parallel to, but different from, Python built-ins such as None, False, and True.

None is a great sentinel value and a classic implementation of the null object pattern.

But there are times that you need more than one nullish value to represent different aspects of emptiness. “Nothing there” is logically different from “undefined,” “prohibited,” “end of data,” and other kinds of “null.”

nulltype helps you easily represent different aspects of emptiness in a way that doesn’t overload None (or False, 0, {}, [], "", or any of the other possible “there’s nothing here!” values). It helps create designated identifiers with specific meanings such as Passthrough, Prohibited, and Undefined.

On the off chance that you need truish sentinels that aren’t True, it will help you do that too. And it will do so in an easily-consumed, right-off-the-shelf, fully-tested tested way.

Usage

from nulltype import NullType

Void = NullType('Void')

# following just to show it's working
assert bool(Void) == False
assert len(EmpVoidty) == 0
assert list(Void) == []
assert Void.some_attribute is Empty
assert Void[22] is Nothing
assert Void("hey", 12) is Empty

You can create as many custom null values as you like. For convenience, several default values, Empty, Null, and Nothing, are exported. That way, if you don’t really want to create your own, you can easily import a pre-constituted null value:

from nulltype import Empty

The Power of Nothing

Alternate null types can be particularly useful when parsing data or traversing data structures which might or might not be present. This is common in dealing with the data returned by REST APIs, for instance.

As one example, the documentation for Google’s Gmail API suggests the following code:

threads = gmail_service.users().threads().list(userId='me').execute()
if threads['threads']:
    for thread in threads['threads']:
        print 'Thread ID: %s' % (thread['id'])

There is a lot going on there just to avoid a problematic deference. If instead you have a Nothing null type defined, the code is shorter (and avoids an extra, very transient variable):

results = gmail_service.users().threads().list(userId='me').execute()
for thread in results.get('threads', Nothing):
    print 'Thread ID: %s' % (thread['id'])

Three lines versus four may not seem like a big advantage, but the value increases with the complexity of the task. Many such “if it’s there, then…” constructs are deeply nested when dealing with API results, XML parse trees, and other fundamentally nested information sources. Saving a guard condition on every one of the nesting levels adds up quickly.

While you could almost do this in stock Python, unlike Nothing, None is not iterable. You might use an empty list [] (or an equivalent global such as EMPTYLIST) as the alternative value for the get method. Going by the documentation of many parsers and APIs, however, such uses aren’t broadly idiomatic in today’s Python community. The EMPTYLIST approach also is very specific to routines returning lists, whereas the “go ahead, get it if you can” nulltype model works well for longer chains of access:

results.get("payload", Nothing).get("headers", Nothing)

will return the correct object if it’s there, but Nothing otherwise. And if you then try to test it (e.g. with if or a logical expression) or iterate over it (e.g. with for), it will act as though it’s an empty list, or False–whatever is most useful in a given context. Whether you’re iterating, indexing, dereferencing, calling, or otherwise accessing it, a NullType is unperturbed.

Nothing isn’t nothing. It’s something that will simplify your code.

General Sentinels and Distinguished Values

While nulltype is frequently used to define new kinds of “empty” values, it’s actually more general. Beyond different forms of ‘null’, NullType instances are good general-purpose sentinels or designated values. Instead of the old:

class MySentinelClass(object):
    pass

Use:

MySentinel = NullType('MySentinel')

That gives you a value with known truthiness properties and a nicer printed representation.:

>>> print MySentinelClass               # fugly
<class '__main__.MySentinelClass'>

>>> print MySentinel                    # just right
MySentinel

On the off chance you want a sentinel value that is truthy rather than falsey / empty, use NonNullType, a companion to NullType that operates in almost the exact same way, but that evaluates as true.:

from nulltype import NonNullType

Full = NonNullType('Full')

assert bool(Full) is True
assert len(Full) == 1
assert list(Full) == [Full]
assert Full.some_attribute is Full
assert Full[22] is Full
assert Full("hey", 12) is Full

Experience suggests that nullish sentinels are generally adequate and preferable. And the “everything folds back to the same value” nature of even NonNullType gives a somewhat null-like, or at least non-reactive, nature. But if you do want a true-ish sentinel, there it is.

Uniqueness

NullType instances are meant to be singletons, with just one per program. They almost are, though technically multiple NullType instances are reasonable, making it more of a multiton pattern.

The uniqueness of each singleton is currently not enforced, making it a usage convention rather than strict law. With even minimal care, this is a problem roughly 0% of the time.

Notes

  • Successfully packaged for, and tested against, all late-model versions of Python: 2.6, 2.7, 3.3, 3.4, 3.5, 3.6, and 3.7 pre-release, as well as recent builds of PyPy and PyPy3.

  • See CHANGES.yml for the complete Change Log.

  • Automated multi-version testing managed with pytest, pytest-cov, coverage and tox. Continuous integration testing with Travis-CI. Packaging linting with pyroma.

  • Similar modules include sentinels and null. Of these, I prefer sentinels because it is clearly Python 3 ready, includes a pickle mechanism. noattr is a new alternative.

  • For a module that uses the null value Empty to make the parsing of JSON and other data formats easier, see items

  • The author, Jonathan Eunice or @jeunice on Twitter, welcomes your comments and suggestions.

Installation

To install or upgrade to the latest version:

pip install -U nulltype

You may need to prefix this with sudo to authorize installation on Unix, Linux, and macOS. In environments without super-user privileges, you may want to use pip’s --user option, to install only for a single user, rather than system-wide. On a system with multiple versions of Python, you may also need to use specific pip3 or pip2 commands instead of the stock pip. As a backup, running pip as a Python module can save your sanity in complex cases where pip versions aren’t working well as standalone commands:

python3.6 -m pip install -U nulltype

Testing

To run the module tests, use one of these commands:

tox                # normal run - speed optimized
tox -e py27        # run for a specific version only (e.g. py27, py34)
tox -c toxcov.ini  # run full coverage tests

Metadata

Release files for nulltype 2.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nulltype 2.3.1
File Size Uploaded Provenance
nulltype-2.3.1.zip 20.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for nulltype 2.3.1
File Interpreter ABI Platform
nulltype-2.3.1-py2.py3-none-any.whl Python 3, Python 2 none any Details

Total release size: 31.2 kB

Release files / nulltype-2.3.1.zip

Download URL nulltype-2.3.1.zip
Size 20.1 kB
Tags Source
SHA-256 checksum
How to use checksums
64aa3cb2ab5e904d1b37175b9b922bea268c13f9ce32e3d373313150ab5ef272
BLAKE2b-256 checksum
How to use checksums
2fce92289851364b7f816a839c8064aac06c01f3a3ecf33ab04adf9d0a0ab66a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release files / nulltype-2.3.1-py2.py3-none-any.whl

Download URL nulltype-2.3.1-py2.py3-none-any.whl
Size 11.1 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
16ae565745118e37e0558441f5821c76351d8c3a789640b5bca277cf65b2271b
BLAKE2b-256 checksum
How to use checksums
000f47dde1a3cceac9858da0bfb92d2279bf5f993ed075b72983e92efc297db3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Security for nulltype 2.3.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page