標籤:python 深複製 淺複製 記憶體 指標
Python是一門很好的語言,他的優點在於擁有巨大靈活性的同時也擁有無比的嚴謹性,其他語言規定了很多文法,告訴你什麼情況下,文法就是這樣的,而Python卻用很少的規定,延伸出很多文法,有些文法看上去很奇怪,仔細分析卻是那麼的合理。今天思考了Python中關於指標和深淺複製的問題,下面希望能通過根據記憶體空間的變化對這些讓人頭疼的問題作出一個解釋。
首先看第一個例子:
a = 1
b = a
b = 2
print ’a = %s‘ %a, ‘b = %s’%b
結果:a = 1 b = 2
當執行a = 1操作時,記憶體中先分配一個整型變數的空間並賦值為1,然後將a指向這塊空間,執行b = a時,將b也指向這塊記憶體,這時,a和b的地位是一樣的。b = 2,按說會把當前b指向的那塊記憶體賦值為2,其實Python並不會這樣做。因為在Python中,整型以及其他基本類型加上字串和元組等是不可以被修改的。意思是他們一旦被聲明,在記憶體上就不能被改變。那麼執行b = 2時發生的是,系統分配一個整型的記憶體,並賦值為,再將這塊記憶體的地址賦給b,因此a和b就指向了不同的值。
在看一個很矛盾的例子:
a=[1,[2],3]
b=a
b[0]=0
print a
結果:[0,[2],3]
這好像不太對,和上面說的有點矛盾,其實並不矛盾。因為列表是可以修改的,a和b指向的是一個列表,其實列表時存的是一組指標。指標是可以修改的。元組不能修改就是因為元組裡的資料是記憶體上的資料本身,而列表裡元素是指標。當使用b修改b[0]時,實際上是將原本指向一個1的指標b[0]同時也是a[0]指向了一個0,而那個1如果沒有別的指標指向他的話,他就被回收了。這個0和1雖然索引一樣,但在記憶體中的位置不同。我無比的希望可以列印指標的內容來驗證我的想法。
記憶體情況如下:
賦值之後:
下面說一下copy()和deepcopy()。
deepcopy()就不用說了,這個就是嚴格的深複製。兩個指標一點關係都沒有,誰也不會影響誰,因為他們在記憶體中是獨立的。而copy就不行了,他是copy()有別於直接賦值,但它又不同於deepcopy()。舉個例子:
import copy
a=[1,[2],3]
b=copy.copy(a)
b[0]=0
b[1].append(2)
print a
結果為:[1,[2,2],3]
折結果看似意外,其實是十分合理的。copy()是一種淺複製,b實際上是a的一個影子,系統也為b分配了自己的空間,意味著a和b指向的記憶體並不相同,但是,b中只複製了a中的指標,意思是b的每一項和a中的每一項指向的記憶體是相同的。當對b[0]賦值為0時,b[0]從指向1改為指向0,而a[0]還是指向1的,因此a的第一項仍為1。而b[1].append(2)時,b[1]和a[1]指向同一個列表,這個列表就是[2]。這條語句並沒有修改指標而是讓[2]增加了一個元素。a[1]和b[1]還是指向這個列表的。因此a[1]變為[2,2]。畫一下的話應該是這個樣子:
是copy()過後的記憶體情況。經過操作後記憶體的情況如下:
上面v就是我對Python記憶體管理和指標的理解。如有錯誤,請指正。
python 深淺複製與指標記憶體