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

偶尔善良 提交于 2019-12-18 13:15:24

问题


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__?


回答1:


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.




回答2:


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




回答3:


The answer is 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 remove from the list iff they are the same object. If they are different object with same value it won;t remove it.



来源:https://stackoverflow.com/questions/8588890/does-a-python-object-which-doesnt-override-comparison-operators-equals-itself

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!