The is and == operators in Python

Beware of confusion between is and == operators in Python

Object identity and numeric equality are not the same.

One thing to consider when comparing numbers or objects using the operators is / == don’t even think they are interchangeable, you will run into problems :)

I found out about it the hard way when writing a little function to check whether a number was a perfect square.

The code in question

import math
def is_square(n):
    if n <= 0:
        return False
    nx = int(round(math.sqrt(n)))
    nxsum = nx*nx
    if nxsum == n:
        return True
    else:
        return False

It’s not particularly nice, but it will serve us as a good example why you should always be aware that == and is are not the same operator in Python nor can they be used interchangeably. It might work sometimes, but then you’re just lucky, don’t do it.

So, I was trying to write my final if statement checking if number n was indeed a perfect square like this

if nxsum is n:
        return True

And I wondered why it wasn’t working. I checked it against randomly created perfect squares, one of them was 88900304 which I will use as example for the rest of this post.

So I was testing is_square(88900304) and upon the errors I encounterd I proceeded to verify in the Python shell what the variables nx and nxsum would hold. I ended up with the somewhat baffling conclusion you can see below:

>>> n
807241744
# nx being the square root of n
>>> nx
28412
# and nxsum should be equal to n
>>> nxsum = nx * nx
>>> nxsum
807241744

nxsum and n look like the same number, my code is correct I thought. I found a perfect square and my function should just return True. But instead it was returning False! When writing that if clause I was completely oblivious to the implications and thought is would just be a somewhat more pythonic way to write ==. Big mistake! They are not the same operator. == is used for numeric equality and is is used to compare object identity.

This means that while both nxsum and n do represent the same numeric value (807241744) they are different objects.

>>> nxsum is n
False
>>> nxsum == n
True

It all makes sense when you check the objects using id()

>>> id(n)
88900864
>>> id(nxsum)
88900320

So while they hold the same numeric value, n is not nxsum in a pythonic sense, as they are different objects in memory.