Is a Python object that does not override comparison operators equal to 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 that was added before it and to which I still have a link. I do not need an equality test. I need an identity test. This code seems to work in both CPython and IronPython, but does the language guarantee this behavior or is it just an accident?

The documentation for the list.remove method is this: same as del s[s.index(x)] , which means the equality test is running.

That way, the object will be equal to itself if you don't override __cmp__ , __eq__ or __ne__ ?

+6
source share
3 answers

Yes In your q.remove(y) example, the first occurrence of an object that is compared to y is deleted. However, as class A is defined, you should not † ever have a comparison value equal to y - with the exception of any other names that are also tied to the same y instance.

The relevant section of the documents is here :

If the operation __cmp__(), __eq__() or __ne__() not defined, the class instances are compared by the identifier of the object ("address").

Thus, the comparison for instances of A carried out by identifier (implemented as a memory address in CPython). No other object can have an identifier equal to id(y) during y lifetime, that is, as long as you keep the link to y (which you must remove if you are going to remove it from the list!)

† Technically, it is still possible to have objects in other memory cells that are compared with equals - mock.ANY is one such example. But these objects must redefine their comparison operators to force the result. Sub>

+9
source

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

+2
source

Answer: yes and no.

Consider the following example.

 >>> class A(object): def __init__(self, value): self.value = value >>> x = A(1) >>> y = A(2) >>> z = A(3) >>> w = A(3) >>> q = [x, y,z] >>> id(y) #Second element in the list and y has the same reference 46167248 >>> id(q[1]) #Second element in the list and y has the same reference 46167248 >>> q.remove(y) #So it just compares the id and removes it >>> q [<__main__.A object at 0x02C19AB0>, <__main__.A object at 0x02C19B50>] >>> q.remove(w) #Fails because though z and w contain the same value yet they are different object Traceback (most recent call last): File "<pyshell#11>", line 1, in <module> q.remove(w) ValueError: list.remove(x): x not in list 

It will be removed from the list if they are the same object. If they are another object with the same value, he won, t delete it.

0
source

Source: https://habr.com/ru/post/904233/


All Articles