tft每日頭條

 > 圖文

 > python怎麼淺拷貝和深拷貝

python怎麼淺拷貝和深拷貝

圖文 更新时间:2024-07-21 22:16:00

python怎麼淺拷貝和深拷貝?首先,我們知道Python3中,有6個标準的數據類型,他們又分為可變和不可變,我來為大家講解一下關于python怎麼淺拷貝和深拷貝?跟着小編一起來看一看吧!

python怎麼淺拷貝和深拷貝(python3淺拷貝與深拷貝的區别和理解)1

python怎麼淺拷貝和深拷貝

首先,我們知道Python3中,有6個标準的數據類型,他們又分為可變和不可變。

不可變數據(3個):

  1. Number(數字)
  2. String(字符串)
  3. Tuple(元組)

可變數據(3個):

  1. List(列表)
  2. Dictionary(字典)
  3. Set(集合)
淺拷貝
  1. 對于 不可 變類型 Number String Tuple,淺複制僅僅是地址指向,不會開辟新空間。
  2. 對于 可 變類型 List、Dictionary、Set,淺複制會開辟新的空間地址(僅僅是最頂層開辟了新的空間,裡層的元素地址還是一樣的),進行淺拷貝
  3. 淺拷貝後,改變原始對象中為可變類型的元素的值,會同時影響拷貝對象的;改變原始對象中為不可變類型的元素的值,隻有原始類型受影響。 (操作拷貝對象對原始對象的也是同理)

可變類型和不可變類型在淺拷貝中的區别

import copy # 不可變類型 Number String Tuple print("對于不可 變類型 Number String Tuple,淺複制僅僅是地址指向,不會開辟新空間拷貝值") num1 = 17 num2 = copy.copy(num1) print("num1:" str(id(num1))) print("num2:" str(id(num1))) # num1和num2的地址都相同 str1 = "hello" str2 = copy.copy(str1) print("str1:" str(id(str1))) print("str2:" str(id(str2))) # str1和str2的地址都相同 tup1 = (18, "tom") tup2 = copy.copy(tup1) print("tup1:" str(id(tup1))) print("tup2:" str(id(tup2))) # tup1和tup2的地址都相同 print("="*20) print("對于可變類型 List、Dictionary、Set,淺複制會開辟新的空間地址(僅僅是最頂層開辟了新的空間),進行淺拷貝") list1 = [11,12] list2 = copy.copy(list1) print("list1:" str(id(list1))) print("list2:" str(id(list2))) # list1和list2的地址不相同 dic1 = [11,12,"hi"] dic2 = copy.copy(dic1) print("dic1:" str(id(dic1))) print("dic2:" str(id(dic2))) # dic1和dic2的地址不相同 set1 = {"AA","BB"} set2 = copy.copy(set1) print("set1:" str(id(set1))) print("set2:" str(id(set2))) # set1和set2的地址不相同

結果:

對于不可 變類型 Number String Tuple,淺複制僅僅是地址指向,不會開辟新空間拷貝值 num1:4449693616 num2:4449693616 str1:4452098488 str2:4452098488 tup1:4451942472 tup2:4451942472 ==================== 對于可變類型 List、Dictionary、Set,淺複制會開辟新的空間地址,進行淺拷貝 list1:4456844424 list2:4452360136 dic1:4452358856 dic2:4456844744 set1:4452279016 set2:4452279464

對list進淺拷貝,對可變類型和不可變類型修改後的影響


import copy l1 = [11, 12] l2 = [21, 22] num = 555 allOne = [l1, l2,num] # 淺拷貝,創建出一個對象,并把舊對象元素的 引用地址 拷貝到新對象當中。 # 也就是說,兩個對象裡面的元素通過淺拷貝指向的還是同一個地址 allOne2 = copy.copy(allOne) l1[0] = 16 # 此處修改,會使得 allOne 和 allOne2的第0個元素的值都發生改變,因為l1是List,是可變對象 allOne[2] = 666 # 此處修改,隻會allOne的num的值,因為不可變對象一旦重新複制,地址就會發生改變。(不可變嘛) num = 777 # 此處不會改變 allOne 和 allOne2的值,因為相當于 777 複制給一個全新的地址,這個num跟其他num已經沒關系了 print(allOne) print(allOne2) print("id allOne:" str(id(allOne))) print("id allOne[0]:" str(id(allOne[0]))) print("id allOne[1]:" str(id(allOne[1]))) print("id allOne[2]:" str(id(allOne[2]))) print("===") print("id allOne2:" str(id(allOne2))) print("id allOne2[0]:" str(id(allOne2[0]))) print("id allOne2[1]:" str(id(allOne2[1]))) print("id allOne2[2]:" str(id(allOne2[2])))

結果:

[[16, 12], [21, 22], 666] [[16, 12], [21, 22], 555] id allOne:4467341640 id allOne[0]:4471819912 id allOne[1]:4467342920 id allOne[2]:4466847696 === id allOne2:4471820232 id allOne2[0]:4471819912 id allOne2[1]:4467342920 id allOne2[2]:4466081744


結論:

  1. 改動allOne中的可變類型,會影響allOne2,改變allOne2同理影響allOne。
  2. 改動allOne2中的不可變類型,隻有allOne2自身會改變,allOne不受影響。

備注:List是可變類型

對于不可變類型被修改後造成的影響,我們用一個更加簡單的例子便可更好理解:

num = 123 print(str(id(num))) num = 666 print(str(id(num)))

結果:

4348603632 4350009296

深拷貝
  1. 淺拷貝,除了頂層拷貝,還對子元素也進行了拷貝(本質上遞歸淺拷貝)
  2. 經過深拷貝後,原始對象和拷貝對象所有的子元素地址都是獨立的了
  3. 可以用分片表達式進行深拷貝
  4. 字典的copy方法可以拷貝一個字典

深拷貝對6種基本類型的影響

我們對3種可變類型3種不可變類型進行深拷貝。
結果發現,和淺拷貝幾乎一緻。

其實這也好理解,因為的深拷貝對比淺拷貝,強調的是 遞歸,強調的是資源素。
對了頂層的操作,深淺拷貝無異。

import copy # 不可變類型 Number String Tuple print("對于不可 變類型 Number String Tuple,深複制依然是地址指向,不會開辟新空間拷貝值") num1 = 17 num2 = copy.deepcopy(num1) # 深拷貝 print("num1:" str(id(num1))) print("num2:" str(id(num1))) # num1和num2的地址都相同 str1 = "hello" str2 = copy.deepcopy(str1) # 深拷貝 print("str1:" str(id(str1))) print("str2:" str(id(str2))) # str1和str2的地址都相同 tup1 = (18, "tom") tup2 = copy.deepcopy(tup1) # 深拷貝 print("tup1:" str(id(tup1))) print("tup2:" str(id(tup2))) # tup1和tup2的地址都相同 print("="*20) print("對于可變類型 List、Dictionary、Set,深拷貝會開辟新的空間地址,進行拷貝") list1 = [11,12] list2 = copy.deepcopy(list1) # 深拷貝 print("list1:" str(id(list1))) print("list2:" str(id(list2))) # list1和list2的地址不相同 dic1 = [11,12,"hi"] dic2 = copy.deepcopy(dic1) # 深拷貝 print("dic1:" str(id(dic1))) print("dic2:" str(id(dic2))) # dic1和dic2的地址不相同 set1 = {"AA","BB"} set2 = copy.deepcopy(set1) # 深拷貝 print("set1:" str(id(set1))) print("set2:" str(id(set2))) # set1和set2的地址不相同

import copy l1 = [11, 12] l2 = [21, 22] num = 555 allOne = [l1, l2,num] # 淺拷貝,除了頂層拷貝,還對子元素也進行了拷貝(本質上遞歸淺拷貝) # 經過深拷貝後,原始對象和拷貝對象所有的元素地址都沒有相同的了 allOne2 = copy.deepcopy(allOne) # copy.deepcopy 深拷貝 allOne[1] = [113,114] allOne2[2] = [227,228] print(allOne) print(allOne2) print("id allOne:" str(id(allOne))) print("id allOne[0]:" str(id(allOne[0]))) print("id allOne[1]:" str(id(allOne[1]))) print("id allOne[2]:" str(id(allOne[2]))) print("===") print("id allOne2:" str(id(allOne2))) print("id allOne2[0]:" str(id(allOne2[0]))) print("id allOne2[1]:" str(id(allOne2[1]))) print("id allOne2[2]:" str(id(allOne2[2])))

結果:

[[11, 12], [113, 114], 555] [[11, 12], [21, 22], [227, 228]] id allOne:4549589640 id allOne[0]:4554067720 id allOne[1]:4554067848 id allOne[2]:4548329424 === id allOne2:4554067912 id allOne2[0]:4554067784 id allOne2[1]:4554067592 id allOne2[2]:4554100808

其他拷貝方式

除了copy模塊的中的copy和deepcopy,還有其他自帶的方式可實現拷貝。

  • 1、分片表達式進行淺拷貝
  • 2、字典的copy方法可以拷貝一個字典

分片表達式拷貝

l1 = [11, 12] l2 = [21, 22] num = 555 orgi = [l1, l2, num] nList = orgi[:] print("orgi:" str(id(orgi))) print("orgi[0]:" str(id(orgi[0]))) print("orgi[1]:" str(id(orgi[1]))) print("orgi[2]:" str(id(orgi[2]))) print("*"*30) print("nList:" str(id(nList))) print("nList[0]:" str(id(nList[0]))) print("nList[1]:" str(id(nList[1]))) print("nList[2]:" str(id(nList[2])))

用分片表達式進行的拷貝,是淺拷貝。

字典自帶的copy方法可實現深拷貝

dic = {"key": "hello", "num": 18} dic2 = dic.copy() dic["key"] = "one" dic2["key"] = "two" print(dic) print("dic:" str(id(dic))) print(dic2) print("dic2:" str(id(dic2)))

結果:

{'key': 'one', 'num': 18} dic:4382946792 {'key': 'two', 'num': 18} dic2:4382946864

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关圖文资讯推荐

热门圖文资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved