Python operator.is_none provides a reusable callable that checks whether a value is exactly None. Instead of writing a lambda every time an API expects a predicate, you can pass operator.is_none directly. Its companion, operator.is_not_none, returns true when the value is anything other than None.
The feature is small, but it improves clarity in filters, validation pipelines, collection processing, callback registries, and functional-style code. It does not replace the familiar value is None expression in ordinary conditionals. Rather, it gives you a named function when the identity test itself must be passed around.
Why None should be checked by identity
None is a singleton used to represent missing information, an unavailable result, or a state that has not been initialized. The recommended comparison is:
value = None
if value is None:
print("missing")
Avoid value == None. User-defined classes may override __eq__, causing equality checks to execute custom code or return surprising results. The is operator checks object identity and is therefore the correct tool for this singleton.
Basic behavior
from operator import is_none, is_not_none
print(is_none(None)) # True
print(is_none(0)) # False
print(is_not_none("")) # True
print(is_not_none(False)) # True
Falsy values are not automatically missing. Zero, an empty string, an empty list, and False may all be valid business values. This distinction matters in forms, configuration files, APIs, and partial updates.
Filtering missing values
from operator import is_not_none
values = [10, None, 0, "", None, 25]
clean = list(filter(is_not_none, values))
print(clean) # [10, 0, '', 25]
Using filter(None, values) would also remove zero and the empty string. The named predicate expresses the exact rule: remove only None.
Collecting missing entries
from operator import is_none, is_not_none
answers = ["yes", None, "no", "", None]
missing = list(filter(is_none, answers))
present = list(filter(is_not_none, answers))
This pattern is useful in data-quality reports, optional-field validation, ETL routines, and form processing.
Using map, any, and all
from operator import is_none
fields = ["Ana", "ana@example.com", None]
has_missing = any(map(is_none, fields))
all_missing = all(map(is_none, fields))
A generator expression such as any(item is None for item in fields) is also excellent and may be easier for many readers. The operator function becomes especially valuable when you need to store, register, or compose the predicate.
Working with itertools
from itertools import filterfalse
from operator import is_none
values = [1, None, 2, None, 3]
present = list(filterfalse(is_none, values))
In this example, filter(is_not_none, values) is shorter, but filterfalse demonstrates how a named predicate can integrate naturally with multiple functional APIs.
Lambda comparison
The traditional equivalent is straightforward:
clean = list(filter(lambda item: item is not None, values))
The lambda remains useful and is compatible with older Python versions. The operator function avoids repeating the same expression and gives stack traces, documentation, and callback tables a meaningful name. A lambda remains preferable when the rule is more complex, such as checking both absence and type constraints.
Cleaning dictionaries
from operator import is_not_none
payload = {
"name": "Ana",
"age": None,
"active": False,
"nickname": "",
}
clean = {
key: value
for key, value in payload.items()
if is_not_none(value)
}
The result keeps False and the empty string while removing only the absent age. This is useful when building HTTP payloads, database updates, and serialized documents.
Optional function arguments
from operator import is_none
def build_update(name=None, active=None):
changes = {}
if not is_none(name):
changes["name"] = name
if not is_none(active):
changes["active"] = active
return changes
A call with name="" intentionally supplies an empty string, while a call without the argument means no update. In larger APIs, a custom sentinel can be even better when you must distinguish “not supplied” from “explicitly supplied as None.”
Predicate registries
Named functions are convenient when validation rules are configured as data.
from operator import is_none, is_not_none
RULES = {
"required_missing": is_none,
"optional_present": is_not_none,
}
result = RULES["optional_present"]("value")
This approach can support schema validators, workflow engines, command-line tools, and reusable data-processing steps without wrapping every rule in a custom function.
Compatibility strategy
Before adopting the functions in a reusable package, verify the minimum Python version supported by the project. For older runtimes, a fallback is simple:
try:
from operator import is_none, is_not_none
except ImportError:
def is_none(value):
return value is None
def is_not_none(value):
return value is not None
For controlled applications, declaring the required Python version in pyproject.toml is usually cleaner than maintaining compatibility branches indefinitely.
Performance considerations
Do not select this feature solely because of a microbenchmark. Identity tests are already inexpensive, and readability is more important in most applications. Use value is None in direct conditionals. Use the operator callable where a function must be passed as an argument or shared among processing steps.
Testing edge cases
from operator import is_none, is_not_none
assert is_none(None)
assert not is_none(False)
assert not is_none(0)
assert not is_none("")
assert is_not_none([])
assert is_not_none({})
Falsy test cases are essential. They protect against accidental refactoring from an identity rule to a truthiness rule.
Common mistakes
Do not use the function to decide whether a collection is empty; use a length or truthiness check for that purpose. Do not treat every None as invalid without understanding the domain. Avoid hiding a simple conditional behind a functional abstraction when it makes the code harder to read. Finally, document whether None means missing, disabled, unknown, or intentionally empty.
Best practices
Keep absence semantics explicit, preserve valid falsy values, and use custom sentinels when an API needs more than two states. Prefer named predicates in callback tables and reusable pipelines, while keeping direct identity expressions in local control flow.
For related topics, read our guides to Python operator, Python itertools, map, filter, and reduce, and Python type hints.
External references include the official operator documentation and PEP 8, which recommends identity comparisons for singletons.
Conclusion
operator.is_none and operator.is_not_none turn precise identity checks into reusable callables. Their main value is not complexity or speed, but intent: they let filters and functional APIs distinguish None from valid falsy values without repeating lambdas. Use them where a predicate is required, and keep using is None for ordinary conditional logic.







