It has nothing to do with the immutability of x
. None
is a singleton for which is
and ==
return identical results, unless the type of x
defines a weird __eq__
method. The name x
is either bound or not bound to the same object as None
. If not, the identity check will always be False
, regardless of what other type it is. The result of the equality check is up to the type of x
, but will be the same as the identity check for most sane classes.
Now the caveat is that while you can't override is
, since that's an identity check done by the interpreter, you can override ==
. Aside from speed and consistency, here's a toy example showing why x is None
is preferable to x == None
:
class Test:
def __eq__(self, other):
if other is None:
return True
return self is other
>>> Test() == None
True
>>> None == Test()
True
>>> Test() is None
False
>>> None is Test()
False
The reason that both Test () == None
and None == Test()
return the same result has to do with how comparisons are evaluated, and the fact that None
does not define an explicit __eq__
method. Normally, the interpreter calls type(left).__eq__(left, right)
on the operands. If the left operand's type does not define __eq__
or the method returns NotImplemented
, it attempts type(right).__eq__(right, left)
. Only if both fail does it fail over to a built-in identity check. Since None
doesn't define an equality check, it will always use the check defined by the other object before failing over to the identity check.