operator.is_none is a predicate from Python’s operator module that returns True only when a value is exactly None. The expression x is None remains the clearest choice inside ordinary conditions, but a named function is useful when an API expects a callable, such as filter, iterator pipelines, validation helpers, or reusable data-cleaning rules.
This guide explains how to use operator.is_none, how it differs from truth-value testing, how to remove only missing values, how to support older Python versions, and which mistakes to avoid.
What operator.is_none does
The function accepts one object and checks identity with the singleton None. It does not use equality and it does not classify every false value as missing. Zero, False, an empty string, and an empty collection all produce False.
from operator import is_none
print(is_none(None)) # True
print(is_none(0)) # False
print(is_none(False)) # False
print(is_none("")) # False
This distinction matters because false values can still be valid application data. A zero price can mean a free product, while None can mean that a price has not been supplied.
Why use it instead of a lambda?
Without a named predicate, developers commonly write lambda value: value is None. That works, but it repeats a common rule and adds visual noise. A standard function communicates intent immediately and can be reused across pipelines.
values = [10, None, 0, None, 25]
missing = list(filter(is_none, values))
print(missing) # [None, None]
The advantage becomes clearer in code with several transformations. The phrase filter(is_none, values) states exactly what is being selected.
Keeping non-None values
To discard only None, combine the predicate with itertools.filterfalse. Do not use filter(None, values) when zeros, empty strings, or False are meaningful, because that form removes every false item.
from itertools import filterfalse
from operator import is_none
values = [0, None, "", 8, False, None]
present = list(filterfalse(is_none, values))
print(present) # [0, "", 8, False]
This pattern is valuable for form data, API responses, database rows, and configuration files where absence must be distinguished from a legitimate false value.
Cleaning API data
Suppose an API returns optional measurements. A value of zero can be a real measurement, while None indicates that the sensor did not report anything. An identity-based predicate preserves that business rule.
measurements = [2.5, None, 0.0, 4.1]
usable = list(filterfalse(is_none, measurements))
Document what None means in each domain. It may mean unknown, not calculated, not applicable, or temporarily unavailable. A clear contract prevents unrelated parts of the codebase from interpreting the same sentinel differently.
Splitting present and missing items
If both groups are required, a single explicit loop is often clearer and avoids traversing the input twice. The predicate can still centralize the rule.
present = []
missing = []
for item in [1, None, 2, None, 0]:
target = missing if is_none(item) else present
target.append(item)
This approach also makes it easy to collect indexes, record metrics, or preserve metadata about why a value is missing.
Compatibility with older Python versions
Before using the function in a reusable package, verify the minimum Python version. If the project must also run where operator.is_none is unavailable, add a small fallback.
try:
from operator import is_none
except ImportError:
def is_none(value):
return value is None
The fallback has the same runtime meaning, so the rest of the application can use one stable name. Internal projects may instead raise their minimum Python version and remove compatibility branches.
Identity is not equality
The recommended check for None is based on identity. Writing value == None can invoke a custom __eq__ implementation and return an unexpected result. operator.is_none follows value is None semantics and does not delegate the comparison to the object.
class Strange:
def __eq__(self, other):
return True
obj = Strange()
print(obj == None) # may be True
print(is_none(obj)) # False
This predictability matters when working with third-party models, proxies, arrays, and objects that overload comparison operators.
When is None is still better
Inside an ordinary if statement, the direct expression is generally more idiomatic and readable. There is no need to replace every existing check.
result = get_result()
if result is None:
handle_missing()
Use the function when a callable is required. Use the expression when the comparison appears directly in control flow.
Lazy pipelines
Named predicates work well with generators because the data can remain lazy and memory efficient.
from itertools import filterfalse
from operator import is_none
records = (parse_line(line) for line in file)
valid_records = filterfalse(is_none, records)
for record in valid_records:
save(record)
Here, parse_line may return None for ignored rows. The filter removes only those rows and preserves any valid object whose boolean value is false.
Static typing considerations
A runtime predicate does not always cause a type checker to narrow Optional[T] automatically after a generic filter. Depending on the checker, a custom predicate using TypeGuard, an explicit generator, or a type annotation may still be needed. Therefore, is_none solves runtime semantics but does not replace every typing tool.
For more context, see the Academify guides on Python type hints, typing.ReadOnly, lambda functions, and iterators and generators.
Testing the rule
Tests should include None, zero, False, empty text, empty collections, and custom objects. This documents the intended identity check and prevents someone from replacing it with a broader truth-value filter later.
def test_is_none():
assert is_none(None)
assert not is_none(0)
assert not is_none(False)
assert not is_none("")
assert not is_none([])
Common mistakes
Do not confuse missing values with all false values. Do not write equality checks against None. Do not add a compatibility fallback without testing the versions you claim to support. Avoid hiding simple control flow behind functional abstractions when a direct loop is clearer.
Best practices
Use operator.is_none when passing a predicate to another API. Prefer is None in direct conditions. Preserve valid false data by using filterfalse(is_none, values). Document the meaning of absence and test edge cases. Keep version compatibility deliberate and temporary.
The official operator module documentation lists the functions available in each Python release. The Python expression reference explains identity operators in detail.
Conclusion
operator.is_none is a small but expressive tool for functional-style filtering and data pipelines. It selects only the None singleton, preserves valid false values, and replaces repetitive lambdas with a standard named predicate. It is most useful when a function object is required, while is None remains the best choice in simple control flow. With careful version support, clear domain semantics, and focused tests, the function helps make optional-value handling safer and easier to read.







