2011-12-21 51 views
6
class A(object): 

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

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

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

我想從列表中刪除之前添加的特定對象,並且我仍然參考該對象。我不想進行平等測試。我想要一個身份測試。這段代碼似乎可以在CPython和IronPython中使用,但語言是否可以保證這種行爲呢,還是隻是一種僥倖?不覆蓋比較運算符的Python對象是否等於自己?

list.remove方法文檔是這樣的:same as del s[s.index(x)],這意味着執行相等性測試。

因此,如果您不覆蓋__cmp____eq____ne__,那麼對象是否等於自身?

回答

9

見。在您的例子q.remove(y)將刪除其中比較有y等於物體的第一次出現,但該類A的定義方式,你不應該曾經有一個變種可比較等於y - 除了任何其他名稱也被綁定到相同的y實例。

該文檔的相關部分是here

如果沒有__cmp__(), __eq__() or __ne__()操作被定義,類 實例由對象標識(「地址」)進行比較。

因此,比較A實例是通過身份(在CPython中實現爲內存地址)。只要你堅持y參考其他任何對象都可以有一個身份等於y的一生中id(y),即對於(你必須,如果你打算從列表中刪除它!)

從技術上講,仍然有可能在其他存儲位置上比較相等的物體 - mock.ANY就是這樣一個例子。但是這些對象需要重寫它們的比較運算符來強制結果。

+1

有趣的是,Python 3中的行爲似乎相反 – 2016-08-27 10:48:29

+1

'__cmp__' [[在Python 3中沒有]](https://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons)。不過,您可以使用'__eq__'實現相同的效果。 – wim 2016-08-27 15:57:11

+0

我想知道是否沒有定義__eq__,Python 3是通過地址比較嗎? – 2016-09-16 04:19:07

0

答案是肯定的,不是。

請看下面的例子

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

它會從列表中刪除當且僅當它們是同一個對象。如果它們是具有相同值的不同對象,則它不會被刪除。

+0

答案很簡單,不是「是,否」。 OP明確表示他們希望進行身份測試,而不是平等測試。 – wim 2011-12-21 11:40:09