问题 删除python列表中的对象实例
我认为这应该有效,但它给了我一个错误。
我有一个包含类对象的列表 node
。我有两个不同的清单
- open_list
- node_list。(它们在纵向上是不一样的,顺序排序)
当我在中找到一个特定的节点时 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。
只是仔细检查
谢谢,
4473
2017-07-12 16:45
起源
答案:
发生这种情况是因为您理解为识别您的两个实例的功能 Node
类,不是python如何理解它。
问题出在这里。假设你问python 5==5
,python会回来 True
。这是因为python知道 int
秒。然而, Node
是您定义的自定义类,因此您需要在两个时告诉python Node
对象是一样的。由于你(可能)没有,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
第二种方法试图删除 x
从 my_list
如果这导致错误,则忽略该错误
12
2017-07-12 16:57
答案:
发生这种情况是因为您理解为识别您的两个实例的功能 Node
类,不是python如何理解它。
问题出在这里。假设你问python 5==5
,python会回来 True
。这是因为python知道 int
秒。然而, Node
是您定义的自定义类,因此您需要在两个时告诉python Node
对象是一样的。由于你(可能)没有,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
第二种方法试图删除 x
从 my_list
如果这导致错误,则忽略该错误
12
2017-07-12 16:57
如果我正确地阅读了这个问题,那么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
2017-07-12 17:15
在回复你的后续行动时,是的 in
将检查列表中的成员身份,因此:
if removed in node_list: node_list.remove(removed)
不会给你错误。或者,您可以捕获错误:
try:
node_list.remove(removed)
except ValueError:
pass
2
2017-07-12 18:36