【问题标题】:Python: List of Objects changes when the object that was input in the append() function changesPython:当在 append() 函数中输入的对象发生变化时,对象列表发生变化
【发布时间】:2014-06-21 20:44:48
【问题描述】:

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

【问题讨论】:

  • 您不会将 副本 放入列表 - 它是对完全相同的对象的引用。
  • 和提示有区别吗?因为在提示符下,当我更改变量时,列表不会更改。如何在列表中按值添加?
  • 在提示中是一样的;没有看到确切的代码,我无法解释为什么你认为它不同。您不能“按值添加” - 它是 Python 中的所有引用。 current_state 之类的名称和list 之类的集合仅提供对底层对象的引用。如果您想要一个单独版本的对象,请定义一个复制它的方法 - 请参阅docs.python.org/2/library/copy.html
  • 在提示符下我做了以下操作:>>> b=[] >>> a=5 >>> b.append(a) >>> a=6 >>> b [5 ]

标签: python list object memory


【解决方案1】:

您的 state 对象是可变的。当您调用current_state.addKey(5) 时,您修改 current_state 但所有指向它的指针 仍然指向它。而在 python 列表中只包含 pointers 到对象。您对可变列表也有同样的看法:

l1 = [ 1, 2]
l2 = l1
l1.append(3)
l2
=> shows [1, 2, 3]

你不能对字符串有相同的东西(例如),因为它们是不可变的。你不能修改它们,只能指向另一个字符串

s1 = "abc"
s2 = s1
s1 = "def"
s2
=> shows "abc"

当您在循环之外创建对象并在循环中对其进行修改并将其添加到列表时,这是一个常见的错误来源:在循环结束时,您有一个列表,其中包含 n 次与 last 相同的对象价值。这不是特定于 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 包含 5 个指向同一 pair 的指针,key=4 和 val=8

【讨论】:

  • 这不能回答 OP 的问题。
  • OP 没有要求正确的代码,而是要求您提供的解释。这是我的错误@Serge。另外,谢谢你的好意。 :)
【解决方案2】:

当我更改在 append 函数中使用的对象时,列表也会更改。

添加对象的副本或新对象,而不是共享同一个对象。

像= 和append 这样的操作共享一个引用并且不创建新对象。您可以通过再次调用 state() 创建一个 new 不同的状态。您可以使用复制模块创建copy:

from copy import deepcopy

visitedStates.append(deepcopy(current_state))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-03
    相关资源
    最近更新 更多