2013-10-06 69 views
3

是否可以在不復制引用的情況下在Python中複製對象?Python防止複製對象作爲參考

例如,如果我定義一個類

class SomeClass: 
    def __init__(self): 
     self.value = 0 

,然後創建一個實例

someObject = SomeClass() 
someObject.value = 12 

,我嘗試將它複製到另一個實例:

anotherObject = someObject 

,並嘗試修改財產,

anotherObject.value = 10 

原來的屬性,都會修改:

print someObject.value #prints 10 

有什麼辦法來防止這種情況的發生?爲了澄清,我希望anotherObject.value包含10,但我想someObject.value仍包含原始12。這在Python中可能嗎?

在此先感謝。

回答

11

的問題是,與

anotherObject = someObject 

你不復制的對象,只是增加一個參考吧。要複製對象,試試這個:

from copy import copy 

anotherObject = copy(someObject) 
3
import copy 

obj2 = copy.deepcopy(obj2) 
3

正如你已經注意到,anotherObject = someObject不會使副本 - 如果你要一個副本,嘗試

import copy 
otherObject = copy.copy(someObject) 

copy.copy VS copy.deepcopy區別在這裏很重要 - 你可以通過copy.copy獲得你所描述的簡單對象,但是更多的嵌套對象需要copy.deepcopy

copy.copy(someObject)僅使對象someObject的副本,但如果someObject包含對可以改變其它的目的(「可變」對象)的引用在

someObject.value.this_one_has_values_too = 4 

someObject.value[0] = 1 

someObject.value['key'] = 'value' 

then 參考文獻將在複製中製作這些對象。如果您使用copy.deepcopy,它們也會被複制。

瞭解這一點的好方法是使用Online Python Tutor(請參閱鏈接的例子),但這裏直接演示了沒有有用的圖形化在線Python Tutor提供的行爲。

>>> import copy 
>>> class Foo(object): 
...  pass 
... 
>>> f = Foo() 
>>> f.value = 1 
>>> f.nested_value = [2,3,4] 
>>> deep = copy.deepcopy(f) 
>>> deep.value = 5 
>>> f.value 
1 
>>> deep.nested_value.append(6) 
>>> f.nested_value 
[2, 3, 4] 
>>> shallow = copy.copy(f) 
>>> shallow.value = 7 
>>> f.value 
1 
>>> shallow.nested_value.append(8) 
>>> f.nested_value 
[2, 3, 4, 8] 

編輯:但是第一個例子中的整數呢?它實際上是在f對象和shallow對象之間共享的,但這不是問題 - 它不可編輯;我們無法改變一個整數對象像1是任何不同,所以我們還不如節省內存,並使用一個對象任何時候任何Python對象需要1

事情參考閱讀有關這內德的Facts and Myths about Python names and values

+0

是什麼'copy'和'deepcopy'之間的區別?另外,你是什麼意思「嵌套對象」?我是python的新手,我只是想盡可能地學習。 –

+0

@ coder108是否有意義?如果沒有,請讓我知道什麼不能,以便我可以改進答案。 – Thomas

+0

哦,我明白你的意思是'嵌套對象'。出於好奇,是不是一個整數也是一個對象?爲什麼不需要'deepcopy'呢?謝謝你的鏈接,順便說一句。這非常有用。 –

1

您可以使用copy了點。請嘗試以下操作:

someObject = SomeClass() 
someObject.value = 12 
anotherObject = copy.copy(someObject) 
anotherObject.value = 10 

現在someObject.value仍將12.你得把import copy在你的腳本的頂部,雖然。