Unravelling `is` and `is not`

As part of this blog series on Python's syntactic sugar, I said in the post on unary arithmetic operators that it might be the most boring post in this series. I think I was wrong. 😄

The operators is and is not are very short. The documentation for the operators says the following:

x is y is true if and only if x and y are the same object.  An Object’s identity is determined using the id() function.  x is not y yields the inverse truth value.

That's it: call id() on the objects in question and see if you got the same/different values for each of the objects.

The bytecode

Disassembling the two operators leads to the following:

>>> def spam():
...   x is y
...   x is not y
... 
>>> import dis
>>> dis.dis(spam)
  2           0 LOAD_GLOBAL              0 (x)
              2 LOAD_GLOBAL              1 (y)
              4 COMPARE_OP               8 (is)
              6 POP_TOP

  3           8 LOAD_GLOBAL              0 (x)
             10 LOAD_GLOBAL              1 (y)
             12 COMPARE_OP               9 (is not)
             14 POP_TOP
             16 LOAD_CONST               0 (None)
             18 RETURN_VALUE
Disassembly of is and is not

If you follow into COMPARE_OP you will see it calls cmp_outcome(). The pertinent lines of that function are:

static PyObject *
cmp_outcome(PyThreadState *tstate, int op, PyObject *v, PyObject *w)
{
    int res = 0;
    switch (op) {
    case PyCmp_IS:
        res = (v == w);
        break;
    case PyCmp_IS_NOT:
        res = (v != w);
        break;
Snippet from cmp_outcome()

What that is showing is that is and is not are doing nothing more than comparing the pointers of the objects in question (which are the location in memory for the objects if you are unfamiliar with what a pointer is; PyPy returns a unique number instead).

The code

That translates is and is not to:

def is_(a: Any, b: Any) -> bool:
    """Check if the arguments are the same object."""
    return id(a) == id(b)


def is_not(a: Any, b: Any) -> bool:
    """Check if the arguments are different objects."""
    return id(a) != id(b)
Implementations of is and is not

This is one of those instances where the tests took up more code than the implementation. 😄

As usual, the source code from this blog post can be found in my desugar project.