在python lis中删除对象的实例

2024-03-28 20:26:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我认为这应该行得通,但它给了我一个错误。 我有一个列表,其中包含类node的对象。我有两个不同的清单

  1. 打开清单
  2. 节点列表(它们纵向不同,顺序不同)

当我在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个项目不用担心) 打印输出:(节点列表中的最后一项与删除的地址匹配:

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

谢谢

随访Q

所以我想检查我要删除的节点是否存在于节点列表中。当我在http://docs.python.org/tutorial/datastructures.html上查找一些简单的列表函数时

如果元素不在列表中,list.index(x)remove.index(x)都会给出一个错误。这导致我的程序停止运行。 要绕过这个问题,我可以在.remove()node in node_list之前使用这个语句吗?我认为in检查元素是否是列表的一部分并返回bool。 只是再核对一下 谢谢


Tags: 对象instanceinnode列表index节点main
3条回答

之所以发生这种情况,是因为您所理解的识别Node类的两个实例的特性,并不是python所理解的。

问题就在这里。假设您问python5==5,python将返回True。这是因为python知道ints。但是,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)

或者

try:
    my_list.remove(x)
except:
    pass

第二个方法试图从my_list中删除x,如果这导致错误,则忽略错误

如果我正确地理解了这个问题,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[:]

为了响应您的后续操作,yesin将检查列表中的成员身份,因此:

if removed in node_list: node_list.remove(removed)

不会给你错误。或者,您可以捕获错误:

try:
    node_list.remove(removed)
except ValueError:
    pass

相关问题 更多 >