我有一个类的对象列表。当我更改我在追加函数中使用的对象时,列表也会更改。这是为什么?我来自C ++所以这很奇怪。
我有以下代码:
class state:
def __init__(self):
self.x=list([])
self.possibleChests=list([])
self.visitedChests=list([])
def __str__(self):
print "x ",
print self.x
print "possibleChests ",
print self.possibleChests
print "visitedChests ",
print self.visitedChests
return ""
def addKey(self,key):
self.x.append(key)
def __eq__(self,other):
if isinstance(other,self.__class__):
return self.__dict__==other.__dict__
else:
return False
current_state=state()
current_state.addKey(4)
current_state.possibleChests.extend([1,2,4])
current_state.visitedChests.append(5)
visitedStates=list([])
visitedStates.append(current_state)
current_state.addKey(5)
if(current_state in visitedStates):
print "Got ya!!"
else:
print "Not in list!!"
我得到了输出:
Got ya!!
我更改了current_state对象,因此它不应该在列表中。
答案 0 :(得分:1)
当我更改我在追加功能中使用的对象时,列表也会更改。
添加对象的副本或新对象,而不是共享同一个对象。
=
和append
等操作共享引用,不创建新对象。您可以通过再次调用 state()来创建新不同状态。您可以使用复制模块创建copy:
from copy import deepcopy
visitedStates.append(deepcopy(current_state))
答案 1 :(得分:1)
您的state
对象是可变的。当您致电current_state.addKey(5)
时,您修改 current_state
但所有指针仍然指向它。并且在python列表中只包含对象的指针。你对可变的列表有同样的看法:
l1 = [ 1, 2]
l2 = l1
l1.append(3)
l2
=> shows [1, 2, 3]
你不能对字符串(例如)使用相同的东西,因为它们是不可变的。您无法修改它们,只能指向另一个字符串
s1 = "abc"
s2 = s1
s1 = "def"
s2
=> shows "abc"
当你在一个循环之外创建一个对象并在循环中修改它并将它添加到一个列表时,这是一个常见的错误来源:在循环结束时,你有一个包含n次同一个对象的列表值。这不是python特有的,但如果只存储指向可变对象的指针,则可以在Java中观察,甚至在C或C ++中也可以观察到。
C ++示例(它不是很好的C ++,但是展示问题的最小值)
class pair {
public:
int key;
int val;
}
pair* map[5];
pair p;
for (i=0; i<5; i++) {
p.key = i;
p.val = 2 * i;
map[i] = &p; // only store pointer
}
在循环结束时,map
包含指向同一pair
的{{1}}和key=4