2014-06-21 70 views
1

我有一個類的對象列表。當我改變我在追加函數中使用的對象時,列表也會改變。這是爲什麼?我來自C++,所以這很奇怪。Python:當在append()函數中輸入的對象發生更改時,對象列表發生更改

我有以下代碼:

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對象,因此它不應該出現在列表中。

+1

你不的端部將*副本*放入列表中 - 這是對*完全相同的對象*的引用。 – jonrsharpe

+0

與提示不同嗎?因爲在提示時,當我更改變量時,列表不會更改。如何在列表中添加值? – user2105632

+0

提示符是一樣的;沒有看到確切的代碼,我無法解釋爲什麼你認爲它是不同的。你不能「按值添加」 - 這是Python中的所有引用。像'current_state'這樣的名字和像'list'這樣的集合只是提供了對底層對象的引用。如果你想要一個獨立版本的對象,定義一個方法來拷貝它 - 參見https://docs.python.org/2/library/copy.html – jonrsharpe

回答

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含有5個指向同一pairkey=4val=8

1

當我改變我在append函數中使用的對象時,列表也會改變。

添加對象的副本對象,而不是共享同一個對象。

=append這樣的操作共享引用並且不創建新對象。通過再次調用狀態(),您可以創建一個不同的狀態新的。您可以通過使用拷貝模塊創建copy

from copy import deepcopy 

visitedStates.append(deepcopy(current_state)) 
相關問題