我认为这应该有效,但它给了我一个错误。
我有一个包含类node
的对象的列表。我有两个不同的列表
当我在open_list
中找到特定节点时,我需要从node_list
中删除它。我知道列表中有存储在其中的对象的地址
所以当我尝试做
时removed = open_list.pop(min_index)
node_list.remove(removed)
它给我一个错误说
node_list.remove(removed)
ValueError: list.remove(x): x not in list
但是列表只包含像指针一样的地址吗?它应匹配相同的地址。我打印出removed
的地址和整个node_list
的地址(现在只有10个项目,不要害怕)
print out :( node_list中的最后一项与删除的地址匹配:
removed: <__main__.node instance at 0x0124A440>
node_list: [<__main__.node instance at 0x01246E90>, <__main__.node instance at 0x01246EE0>, <__main__.node instance at 0x0124A300>, <__main__.node instance at 0x0124A328>, <__main__.node instance at 0x0124A350>, <__main__.node instance at 0x0124A378>, <__main__.node instance at 0x0124A3A0>, <__main__.node instance at 0x0124A3C8>, <__main__.node instance at 0x0124A3F0>, <__main__.node instance at 0x0124A418>, <__main__.node instance at 0x0124A440>]
由于
所以我想检查node_list中是否存在我要删除的节点。当我在http://docs.python.org/tutorial/datastructures.html
上查找一些简单的列表函数时 如果元素不在列表中, list.index(x)
和remove.index(x)
都会出错。这导致我的程序停止运行。
绕过这个,我可以在.remove()
:node in node_list
之前使用这个语句我认为in
检查一个元素是否是列表的一部分并返回一个bool。
只是仔细检查
谢谢,
答案 0 :(得分:12)
这种情况正在发生,因为您理解为识别Node
类的两个实例的特征,而不是python如何理解它。
问题出在这里。假设您询问了python 5==5
,python将返回True
。这是因为python知道int
s。但是,Node
是您定义的自定义类,因此当两个Node
对象相同时,您需要告诉python。由于你(可能)没有,python默认比较它们在内存中的位置。由于两个独立的实例将位于两个不同的内存位置,因此python将返回False
。如果您熟悉Java,这就像==
和.equals(...)
之间的差异
要执行此操作,请转到Node
课程并定义__eq__(self, other)
方法,其中other
应为Node
的另一个实例。
例如,如果您的节点有一个名为name
的属性,并且两个具有相同名称的节点被认为是相同的,那么您的__eq__
可能如下所示:
def __eq__(self, other):
myName = self.name
hisName = other.name
if myName == hisName:
return True
else:
return False
当然,编写相同功能的更优雅方式是:
def __eq__(self, other):
return self.name == other.name
完成后,您的错误将消失
编辑1 :回复DSM的评论
class Node: pass
a = [Node(), Node()]
b = a[:]
b.remove(a.pop(0))
这会奏效。但仔细观察后,很明显a [0]和b [0]实际上是同一个对象。这可以通过调用id(a[0])
并将其与id(b[[0])
进行比较来确认它们确实相同来验证
编辑2 :回应OP的后续问题(将原始问题添加为编辑)
是的,列表中不存在的对象将导致错误,该错误通常会停止程序流。这可以通过以下两种方式之一解决:
if x in my_list:
my_list.remove(x)
OR
try:
my_list.remove(x)
except:
pass
第二种方法尝试从x
中删除my_list
,如果这会导致错误,则忽略错误
答案 1 :(得分:2)
如果我正确地阅读了这个问题,那么python默认比较内存位置就是他正在寻找的行为,但是没有得到。这是一个定义自定义类Node
的工作示例,它表明不需要__eq__(self, other)
。
class Node(object):
pass
open_node_list = []
node_list = []
for i in range(10):
a_node = Node()
open_node_list.append(a_node)
node_list.append(a_node)
removed = open_node_list.pop()
node_list.remove(removed)
我无法确定,因为您没有显示open_node_list
和node_list
的定义位置,但我怀疑列表本身引用了相同的列表对象。如果是这种情况,open_node_list
的弹出也会从node_list
弹出,因此当您致电remove
时,该节点将不再存在。以下是node_list
和open_node_list
实际上是相同列表的示例,因此更改为一个会影响另一个:
class Node(object):
pass
open_node_list = []
node_list = open_node_list # <-- This is a reference, not a copy.
open_node_list.append(Node())
print(node_list)
您可以复制列表的一种方法是:
node_list = open_node_list[:]
答案 2 :(得分:2)
在回复您的跟进时,是in
将检查列表中的成员身份,因此:
if removed in node_list: node_list.remove(removed)
不会给你错误。或者,您可以捕获错误:
try:
node_list.remove(removed)
except ValueError:
pass