假设我有一个应用程序列表,描述为自定义对象。我决定对原始应用程序列表进行深度复制,这样我就可以有一个列表,就像一个可用的应用程序池。要分配应用程序,我随机选择池的子集,然后在原始列表中找到这些应用程序,以便我可以更新它们的信息。然后,从池中删除已分配的应用程序。但是,由于某种原因,在原始列表中永远找不到应用程序:
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 :(得分:0)
使用list.index
时,它会使用比较运算符(==
)检查项目是否相同,然后使用__eq__
方法,from documentation:
默认情况下,用户定义的类具有
__eq__()
和__hash__()
方法;与他们一起,所有对象比较不等(除了他们自己)和x.__hash__()
返回一个适当的值,x == y
同时暗示x is y
和hash(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()
中返回对象的内存地址,因此如果ids匹配,__eq__
将返回true:
>>> 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__()
,则其实例将无法用作可展开集合中的项。