删除python列表中的对象实例

时间:2012-07-12 16:45:15

标签: python list compare

我认为这应该有效,但它给了我一个错误。 我有一个包含类node的对象的列表。我有两个不同的列表

  1. open_list
  2. node_list。(它们在纵向上是不一样的,按顺序排列)
  3. 当我在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。 只是仔细检查 谢谢,

3 个答案:

答案 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_listnode_list的定义位置,但我怀疑列表本身引用了相同的列表对象。如果是这种情况,open_node_list的弹出也会从node_list弹出,因此当您致电remove时,该节点将不再存在。以下是node_listopen_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