is not
Different objects — and the standard "has a value" check: `if x is not None:`.
Common call
if x is not None:
Returns
bool
Replaces
preferred over `not (x is None)` and `x != None`
Watch out
same caching caveats as is — never for numbers/strings
aa — Left operand.type: Any · required is not bb — Right operand.type: Any · required
→ bool
Operands
| Name | Type | Required | Description |
|---|---|---|---|
| a | Any | yes | Left operand. |
| b | Any | yes | Right operand. |
Return value
bool — True when a and b are DIFFERENT objects. One operator token — not `is` followed by `not`.
Common patterns
The presence check
The counterpart of the None guard.
if result is not None: use(result)
Preserving falsy-but-valid values
Where `or` would clobber 0 / "" / [], identity keeps them.
port = cfg_port if cfg_port is not None else 8080
Examples
1. Has a value
x = 0
x is not None
Returns
True2. Different objects
[1, 2] is not [1, 2]
Returns
TruePitfalls
1. `a is (not b)` is a different expression
Parenthesizing wrongly turns identity into a bool comparison.
Wrong parse
x is (not None) # x is True?!
compares x with the bool True
One token
x is not None
negated identity
When to use
Use it
- "Has a real value" guards
- Distinguishing None from falsy-but-valid data
Reach for something else
- Value inequality → !=
- Numbers/strings → never identity
Notes
Complexity
O(1)
Return
bool
CPython impl
IS_OP with invert flag — one opcode
Memory
No allocation
Thread-safe
Yes
FAQ
Identity cannot be overridden; __ne__ can. And the idiom signals intent: you are testing for the singleton, not comparing values.
History
1.0
Core operator from the beginning.