python 淺拷貝與深拷貝

來源:互聯網
上載者:User

標籤:python   變數   淺拷貝   深拷貝   

python變數在記憶體中是這樣儲存的: 

在python中,一切都是對象,對象的儲存是引用儲存,儲存的只是變數的值所在的記憶體位址,而不是這個變數的值本身。 



如果對值進行修改,其實是在記憶體中新建立一個值,把變數指向這個值的地址



可以看出地址發生了改變

如果是兩個值相等,那麼改變其中一個不會影響另一個


a=b時a,b指向同一個地址

改變a的值後b不會改變


說明是在記憶體中新建立了一個值,a指向了這個值的地址 



這是基本類型的儲存

python中可以分兩大類資料類型,一種是基礎資料類型,如 int str float,long ,bool等基礎類型,另一種是list,tulpe,dict,set等複雜類型,list,tulpe,dict,set中包含基礎類型

由於python中的變數都是採用的引用儲存,而list,tuple,dict這種資料結構可以包含基礎資料類型,這就導致了每個變數中都儲存了這個變數的地址,而不是值本身;對於複雜的資料結構來說,裡面的儲存的也只是每個元素的地址而已。

如果是list列表的儲存形式:

L = [1,2,3,'a','b','c']

print(id(L))

變數L的地址為



每個元素的地址為

L = [1,2,3,'a','b','c']

#print(id(L))

print(id(L[0]))

print(id(L[1]))

print(id(L[2]))

print(id(L[3]))

print(id(L[4]))



L所存的就是這些元素的地址

在記憶體表現形式為:

將列表L的內容賦值給另一個變數和字元的操作一樣

L = [1,2,3,'a','b','c']

Y = L

print(L)

print(Y)

print(id(L))

print(id(Y))




對L追加元素:

L = [1,2,3,'a','b','c']

Y = L

print(L)

print(Y)

print(id(L))

print(id(Y))

L.append("f")

print(L)

print(Y)

print(id(L))

print(id(Y))



如果重新賦值或者說重新初始化,那麼會重新分配新的記憶體空間

L = [1,2,3,'a','b','c']

Y = L

print(L)

print(Y)

print(id(L))

print(id(Y))

L.append("f")

print(L)

print(Y)

print(id(L))

print(id(Y))

L = ['a','b','c']

print(L)

print(Y)

print(id(L))

print(id(Y))



也就是說如果在地址上操作那麼指向這兩個地址的變數的內容都會改變但是地址指向不變

如果重新賦值,那麼重新賦值的那個變數地址就會指向新的記憶體位址

這就是變數賦值的過程

淺拷貝

淺拷貝:不管多麼複雜的資料結構,淺拷貝都只會copy一層。

基礎資料的拷貝,不管淺拷貝還是深拷貝都一樣都會重新分配記憶體位址

#基礎資料拷貝

import copy

L = [1,2,3,'a','b']

M = copy.copy(L)

print(L)

print(M)

print(id(L))

print(id(M))




import copy

L = [1,2,3,'a','b']

M = copy.copy(L)

print(L)

print(M)

print(id(L))

print(id(M))

#給L追加一個元素M不會變

L.append("c")

print(L)

print(M)

print(id(L))

print(id(M))




深拷貝基礎資料:

import copy

L = [1,2,3,'a','b']

M = copy.deepcopy(L)

print(L)

print(M)

print(id(L))

print(id(M))

#給L追加一個元素M不會變

L.append("c")

print(L)

print(M)

print(id(L))

print(id(M))



結果和淺拷貝一樣

複雜的資料:

僅僅對外層修改拷貝後L改變M不變

import copy

L = [1,2,[3,4,'c','d'],'a','b']

M = copy.copy(L)

print(L)

print(M)

print(id(L))

print(id(M))

#給L追加一個元素M不會變

L.append("c")

print(L)

print(M)

print(id(L))

print(id(M))




對內層改變,那麼拷貝後都會變

import copy

L = [1,2,[3,4,'c','d'],'a','b']

M = copy.copy(L)

print(L)

print(M)

print(id(L))

print(id(M))

L[2].append("e")

print(L)

print(M)

print(id(L))

print(id(M))

這說明對內層資料的修改會改變另一個拷貝的對象

在記憶體中的形式為:


可以看出,內層list[1,2]也是一個地址,裡面存的就是元素1,2的地址

所以對L的內層操作就是對內層list[1,2]地址的操作,這樣就會改變M

深度拷貝:

import copy

L = [1,2,[3,4,'c','d'],'a','b']

M = copy.deepcopy(L)

print(L)

print(M)

print(id(L))

print(id(M))

#給L追加一個元素M不會變

L[2].append("e")

print(L)

print(M)

print(id(L))

print(id(M))


可以看出L改變M不變 

在記憶體中的形式:


相當於所有的都拷貝一份

1、對於複雜的資料結構copy.copy 淺拷貝 只拷貝父物件(最外一層),不會拷貝對象的內部(內層資料)的子物件。

2、copy.deepcopy 深拷貝 拷貝父物件(外層資料)及其子物件(內層資料)

3、對於基礎資料型別 (Elementary Data Type)深拷貝淺拷貝都一樣,都會產生新的資料空間

python 淺拷貝與深拷貝

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.