Python:当append()函数中输入的对象发生更改时,对象列表会发生变化

时间:2014-06-21 20:44:48

标签: python list object memory

我有一个类的对象列表。当我更改我在追加函数中使用的对象时,列表也会更改。这是为什么?我来自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对象,因此它不应该在列表中。

2 个答案:

答案 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

的5个指针