2013-04-16 76 views
2

說我有一個應用程序列表,描述爲自定義對象。我決定對原始應用程序列表進行深度拷貝,以便我可以擁有一個充當可用應用程序池的列表。要分配應用程序,我隨機選擇池的一個子集,然後在原始列表中找到這些應用程序,以便我可以更新其信息。然後,分配的應用程序將從池中移除。但是,出於某種原因,應用程序不能再在原來的列表中找到:自定義對象列表的深度複製

list1 = [App1,App2,App3,App4,App5] 
pool = copy.deepcopy(list1) 
num_apps = rand.randrange(0,5) 
random.shuffle(pool) 
selected_apps = copy.deepcopy(pool[:num_apps]) 
for app in selected_apps: 
    locn = list1.index(app) 
    print locn 

上面的代碼實際上將返回一個ValueError在selected_apps一個項目不能被發現。由於我正在製作包含非本地Python對象或其他內容的列表的深層副本,這是否是錯誤?

+0

你是否爲你的App類實現了''__eq__'''方法? 更可能發生的情況是.index方法無法比較兩個App對象,因爲您已經完成了深度複製並且其內存地址已更改,所以這兩個App對象是相同的。 – Necrolyte2

+0

啊,我還沒有嘗試過實施'__eq__'方法。我會研究它,謝謝! –

回答

0

當使用list.index它使用比較運算符(==)檢查項目是否是相同的,並且是使用__eq__方法,from documentation

用戶定義的類具有__eq__()__hash__()方法默認;與他們,所有對象比較不相等(除本身之外)x.__hash__()返回一個適當的值,以便x == y暗示x is yhash(x) == hash(y)

您可以證明這一點:一個對象的

>>> class A(object): 
...  def __init__(self): 
...   self.x = 0 
... 
>>> a = A() 
>>> a.x = 5 
>>> b = a 
>>> b == a 
True 
>>> c = copy.deepcopy(a) 
>>> c == a 
False 

在CPython中id()回報內存地址,所以__eq__返回true,如果ID匹配:

>>> id(a) 
140389541757224 
>>> id(b) 
140389541757224 
>>> id(c) 
140389541757336 

所以,你只需要實現__eq__方法和__ne__

比較運算符之間沒有隱含的關係。 x==y的事實並不意味着x!=y是錯誤的。因此,在定義__eq__()時,還應該定義__ne__(),以便操作員按照預期行事。

>>> class A(object): 
...  def __init__(self): 
...   self.x = 0 
...  def __eq__(self, o): 
...   return self.x == o.x 
...  def __ne__(self, o): 
...   return self.x != o.x 
... 
>>> a = A() 
>>> a.x = 5 
>>> b = a 
>>> c = copy.deepcopy(a) 
>>> d = A() 
>>> d.x = 4 
>>> a == b 
True 
>>> a == c 
True 
>>> a is b 
True 
>>> a is c 
False 
>>> a == d 
False 

還要注意這樣的:

如果一個類沒有定義__eq__()方法不應該限定__hash__()操作要麼;如果它定義了__eq__()而不是__hash__(),則其實例將不可用作可哈希集合中的項目