Today’s fun was trying to figure out what the ‘==’ operator does in Python…and whether it’s in fact being used to implement the ‘in’ operator (i.e. if a in [1,2,3,4]). Seems like good stuff to know, but go try and find docs.

So we started with

>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]
>>> b = [a,a,a,a]
>>> b
[[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]
>>> c = a
>>> a == c
True
>>> c = a[:]
>>> a == c
True

Which seems like we’re checking for value equality. But wait…

>>> class MyInt:
... def __init__(self, i):
... self.i = i
...
>>> a = MyInt(5)
>>> a

>>> b = MyInt(5)
>>> b

>>> a == b
False
>>> a == a
True

How odd. When I made my own class, it used pointer equality to implement ‘==’. I should mention here that I verified that I can define MyInt.__eq__(self,other) to do the right ( return(self.i == other.i) ) thing. But the default checks pointers.

So I thought about it, and no matter how I slice it, the pointer equality check is wrong behaviour, which is to say that it is not what I want in the majority of cases. The C++ compiler also generates the ‘==’ operator if you don’t define it, but there the default is the sensible answer…member by member equality over all member variables. So why did the Guido in the Basement make this choice?

Well, in python I can add and delete instance attributes (or whatever made up terminology the pythonistas are using today) willy nilly. So it’s impossible for the runtime to deliver any sensible == operator based on the attributes, unless I explicitly tell it which ones to use by defining the operator myself. Guido was backed into a corner by his own free and easy, batteries included lifestyle. So he did what any sensible benevolent dictator would — he punted, and let me pay the debugging price once again.

Something to say?