Python has two very similar comparison operators: == for equality and is for object identity. Typically, is faster, as the implementation just needs to compare object ids, whereas == must call the __eq__ method, and is therefor slower.

The operator is is recommended for comparisons with None in Python (as in if a is None). And I was asking myself how much overhead the == method would be in this case. So I figured that the None == None case might be more efficient, than the generic a == None case, because the runtime could first check for identity before deciding to call __eq__.

As it happens, Python has strange semantics with respect to these operators, and my assumption was wrong. I was assuming that a == a was always True (since a is a is True, and identity should imply equality). This is, however, not the case:

(tested with Python 3.5).1

I haven’t found much in the Python docs2 about this, but I guess that someone has a use case where a==a should evaluate to false, although objects are identical. Another explanation would be that if __eq__ would have a side-effect, it should be called in any case, even for identical objects. Right now, I cannot think of any cases where either of these options would be desirable. So if you stumble over classes where a == a does not evaluate to True it might be worth investigating.

# Footnotes

1. Ruby does not do it any other way. I find it a bit less surprising, here, as we direcly overwrite the == operator that is called later, instead of Python’s approach of using a protocol method __eq__:

irb(main):001:0> class A
irb(main):002:1>     def ==(rhs)
irb(main):003:2>         false
irb(main):004:2>     end
irb(main):005:1> end
irb(main):011:0> a = A.new
=> #<A:0x007fda8190f2c8>
irb(main):013:0> a == a
=> false
irb(main):015:0> a === a
=> true