Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a Python object which doesn't override comparison operators equals itself?

class A(object):

    def __init__(self, value):
        self.value = value

x = A(1)
y = A(2)

q = [x, y]
q.remove(y)

I want to remove from the list a specific object which was added before to it and to which I still have a reference. I do not want an equality test. I want an identity test. This code seems to work in both CPython and IronPython, but does the language guarantee this behavior or is it just a fluke?

The list.remove method documentation is this: same as del s[s.index(x)], which implies that an equality test is performed.

So will an object be equal to itself if you don't override __cmp__, __eq__ or __ne__?

like image 947
Meh Avatar asked Dec 21 '11 11:12

Meh


People also ask

How do you check if an object is equal to another object Python?

The == operator compares the value or equality of two objects, whereas the Python is operator checks whether two variables point to the same object in memory. In the vast majority of cases, this means you should use the equality operators == and !=

Is is the same as == in Python?

Put simply: == determines if the values of two objects are equal, while is determines if they are the exact same object.

Why do we use == in Python?

The == operator helps us compare the equality of objects. The is operator helps us check whether different variables point towards a similar object in the memory. We use the == operator in Python when the values of both the operands are very much equal.


2 Answers

Yes. In your example q.remove(y) would remove the first occurrence of an object which compares equal with y. However, the way the class A is defined, you shouldn't ever have a variable compare equal with y - with the exception of any other names which are also bound to the same y instance.

The relevant section of the docs is here:

If no __cmp__(), __eq__() or __ne__() operation is defined, class instances are compared by object identity ("address").

So comparison for A instances is by identity (implemented as memory address in CPython). No other object can have an identity equal to id(y) within y's lifetime, i.e. for as long as you hold a reference to y (which you must, if you're going to remove it from a list!)

Technically, it is still possible to have objects at other memory locations which are comparing equal - mock.ANY is one such example. But these objects need to override their comparison operators to force the result.

like image 191
wim Avatar answered Oct 14 '22 19:10

wim


In python, by default an object is always equal to itself (the only exception I can think of is float("nan"). An object of a user-defined class will not be equal to any other object unless you define a comparison function.

See also http://docs.python.org/reference/expressions.html#notin

like image 45
sverre Avatar answered Oct 14 '22 19:10

sverre