python 賦值,python基礎知識5——賦值與深淺拷貝——整數和字符串,列表元組字典

 2023-10-25 阅读 27 评论 0

摘要:深淺copy ? ?? ? 和很多語言一樣,Python中也分為簡單賦值、淺拷貝、深拷貝這幾種“拷貝”方式。 在學習過程中,一開始對淺拷貝理解很模糊。不過經過一系列的實驗后,我發現對這三者的概念有了進一步的了解。 一、賦值 賦值算是這三種操作中最常見的了&#x

深淺copy ? ??

?

和很多語言一樣,Python中也分為簡單賦值、淺拷貝、深拷貝這幾種“拷貝”方式。

在學習過程中,一開始對淺拷貝理解很模糊。不過經過一系列的實驗后,我發現對這三者的概念有了進一步的了解。

一、賦值

賦值算是這三種操作中最常見的了,我們通過一些例子來分析下賦值操作:

python 賦值?str例

1 >>> a = 'hello'
2 >>> b = 'hello'
3 >>> c = a
4 >>> [id(x) for x in a,b,c]
5 [4404120000, 4404120000, 4404120000]

由以上指令中,我們可以發現a, b, c三者的地址是一樣的。所以以上賦值的操作就相當于c = a = b = 'hello'。

?

賦值是系統先給一個變量或者對象(這里是'hello')分配了內存,然后再將地址賦給a, b, c。所以它們的地址是相同的。

list例

1 >>> a = ['hello']
2 >>> b = ['hello']
3 >>> c = a
4 >>> [id(x) for x in a,b,c]
5 [4403975952, 4404095096, 4403975952]

但是這種情況卻不一樣了,a和b的地址不同。為何?

Python字典賦值,?

因為str是不可變的,所以同樣是'hello'只有一個地址,但是list是可變的,所以必須分配兩個地址。

這時,我們希望探究以上兩種情況如果 修改值 會如何?

str例

1 >>> a = 'world'
2 >>> [id(x) for x in a,b,c]
3 [4404120432, 4404120000, 4404120000]
4 >>> print a, b, c
5 world hello hello

這時a的地址和值變了,但是b, c地址和值都未變。因為str的不可變性,a要重新賦值則需重新開辟內存空間,所以a的值改變,a指向的地址改變。b, c由于'hello'的不變性,不會發生改變。

?

python 淺拷貝?list例

1 >>> a[0] = 'world'
2 >>> [id(x) for x in a,b,c]
3 [4403975952, 4404095096, 4403975952]
4 >>> print a, b, c
5 ['world'] ['hello'] ['world']

這時a, c的值和地址均改變,但二者仍相同,b不改變。由于list的可變性,所以修改list的值不需要另外開辟空間,只需修改原地址的值。所以a, c均改變。

?

在了解了以上的不同點之后,我們就能很好地分析淺拷貝和深拷貝了。

我們均用list作為例子。

二、淺拷貝

1 >>> a = ['hello', [123, 234]]
2 >>> b = a[:]
3 >>> [id(x) for x in a,b]
4 [4496003656, 4496066752]
5 >>> [id(x) for x in a]
6 [4496091584, 4495947536]
7 >>> [id(x) for x in b]
8 [4496091584, 4495947536]

python列表去重,Line3,4可以看出a, b地址不同,這符合list是可變的,應開辟不同空間。那淺拷貝就是拷貝了一個副本嗎?再看Line5 - 8,我們發現a, b中元素的地址是相同的。如果說字符串'hello'地址一致還能理解,但是第二個元素是list地址仍一致。 這就說明了淺拷貝的特點,只是將容器內的元素的地址復制了一份 。

?

接著我們嘗試修改a, b中的值:

1 >>> a[0] = 'world'
2 >>> a[1].append(345)
3 >>> print 'a = ', a, '\n\r', 'b = ', b
4 a =  ['world', [123, 234, 345]] 
5 b =  ['hello', [123, 234, 345]]

a中第一個元素str改變,但是b中未改變;a中第二個元素改變,b中也改變。這就符合不可變的對象修改會開辟新的空間,可變的對象修改不會開辟新空間。也進一步證明了 淺拷貝僅僅是復制了容器中元素的地址 。

?

三、深拷貝

1 >>> from copy import deepcopy
2 >>> a = ['hello', [123, 234]]
3 >>> b = deepcopy(a)
4 >>> [id(x) for x in a, b]
5 [4496066824, 4496066680]
6 >>> [id(x) for x in a]
7 [4496091584, 4496067040]
8 >>> [id(x) for x in b]
9 [4496091584, 4496371792]

深淺拷貝,深拷貝后,可以發現a, b地址以及a, b中元素地址均不同。這才是完全 拷貝了一個副本 。

?

修改a的值后:

1 >>> a[0] = 'world'
2 >>> a[1].append(345)
3 >>> print 'a = ', a, '\n\r', 'b = ', b
4 a =  ['world', [123, 234, 345]] 
5 b =  ['hello', [123, 234]]

從Line4,5中可以發現僅僅a修改了,b沒有任何修改。 因為b是一個完全的副本,元素地址均與a不同,a修改,b不受影響 。

?

總結:

python 數組,1. 賦值是將一個對象的地址賦值給一個變量,讓變量指向該地址( 舊瓶裝舊酒 )。

2. 淺拷貝是在另一塊地址中創建一個新的變量或容器,但是容器內的元素的地址均是源對象的元素的地址的拷貝。也就是說新的容器中指向了舊的元素( 新瓶裝舊酒 )。

3. 深拷貝是在另一塊地址中創建一個新的變量或容器,同時容器內的元素的地址也是新開辟的,僅僅是值相同而已,是完全的副本。也就是說( 新瓶裝新酒 )。

 1 import copy
 2 a = [1, 2, 3, 4, ['a', 'b']]  #原始對象
 3  
 4 b = a  #賦值,傳對象的引用
 5 c = copy.copy(a)  #對象拷貝,淺拷貝
 6 d = copy.deepcopy(a)  #對象拷貝,深拷貝
 7  
 8 a.append(5)  #修改對象a
 9 a[4].append('c')  #修改對象a中的['a', 'b']數組對象
10  
11 print 'a = ', a
12 print 'b = ', b
13 print 'c = ', c
14 print 'd = ', d
15  
16 輸出結果:
17 a =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]
18 b =  [1, 2, 3, 4, ['a', 'b', 'c'], 5]
19 c =  [1, 2, 3, 4, ['a', 'b', 'c']]
20 d =  [1, 2, 3, 4, ['a', 'b']]

一、數字和字符串

對于 數字 和 字符串 而言,賦值、淺拷貝和深拷貝無意義,因為其永遠指向同一個內存地址。

 1 import copy2 # ######### 數字、字符串 #########3 n1 = 1234 # n1 = "i am alex age 10"5 print(id(n1))6 # ## 賦值 ##7 n2 = n18 print(id(n2))9 # ## 淺拷貝 ##
10 n2 = copy.copy(n1)
11 print(id(n2))
12   
13 # ## 深拷貝 ##
14 n3 = copy.deepcopy(n1)
15 print(id(n3))

?

?

python123。?

二、其他基本數據類型

對于字典、元祖、列表 而言,進行賦值、淺拷貝和深拷貝時,其內存地址的變化是不同的。

1、賦值

賦值,只是創建一個變量,該變量指向原來內存地址,如:

1 n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}
2   
3 n2 = n1

?

  

python中深拷貝和淺拷貝??

2、淺拷貝

淺拷貝,在內存中只額外創建第一層數據

1 import copy
2   
3 n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}
4   
5 n3 = copy.copy(n1)?

?

3、深拷貝

python如何給字典賦值。深拷貝,在內存中將所有的數據重新創建一份(排除最后一層,即:python內部對字符串和數字的優化)

1 import copy
2   
3 n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}
4   
5 n4 = copy.deepcopy(n1)

?

為什么要拷貝?

當進行修改時,想要保留原來的數據和修改后的數據

數字字符串 和 集合 在修改時的差異?(深淺拷貝不同的終極原因)

1 在修改數據時:
2   數字字符串:在內存中新建一份數據
3        集合:修改內存中的同一份數據

python深拷貝和淺拷貝,對于集合,如何保留其修改前和修改后的數據?

在內存中拷貝一份

對于集合,如何拷貝其n層元素同時拷貝?

深拷貝

 1 淺copy2 >>> dict = {"a":("apple",),"bo":{"b":"banna","o":"orange"},"g":["grape","grapefruit"]}3 >>> dict = {"a":("apple",),"bo":{"b":"banna","o":"orange"},"g":["grape","grapefruit"]}4 >>> dict2 = dict.copy()5 6 7 >>> dict["g"][0] = "shuaige"  #第一次我修改的是第二層的數據8 >>> print dict9 {'a': ('apple',), 'bo': {'b': 'banna', 'o': 'orange'}, 'g': ['shuaige', 'grapefruit']}
10 >>> print dict2
11 {'a': ('apple',), 'bo': {'b': 'banna', 'o': 'orange'}, 'g': ['shuaige', 'grapefruit']}
12 >>> id(dict["g"][0]),id(dict2["g"][0])
13 (140422980581296, 140422980581296)  #從這里可以看出第二層他們是用的內存地址
14 >>>
15 
16 
17 >>> dict["a"] = "dashuaige"  #注意第二次這里修改的是第一層
18 >>> print dict
19 {'a': 'dashuaige', 'bo': {'b': 'banna', 'o': 'orange'}, 'g': ['shuaige', 'grapefruit']}
20 >>> print dict2
21 {'a': ('apple',), 'bo': {'b': 'banna', 'o': 'orange'}, 'g': ['shuaige', 'grapefruit']}
22 >>>
23 >>> id(dict["a"]),id(dict2["a"])
24 (140422980580816, 140422980552272)  #從這里看到第一層他們修改后就不會是相同的內存地址了!
25 >>>
26 
27 
28 #這里看下,第一次我修改了dict的第二層的數據,dict2也跟著改變了,但是我第二次我修改了dict第一層的數據dict2沒有修改。
29 說明:淺copy只是第一層是獨立的,其他層面是公用的!作用節省內存
30 
31 深copy
32 
33 >>> import copy  #深copy需要導入模塊
34 >>> dict = {"a":("apple",),"bo":{"b":"banna","o":"orange"},"g":["grape","grapefruit"]}
35 >>> dict2 = copy.deepcopy(dict)
36 >>> print dict
37 {'a': ('apple',), 'bo': {'b': 'banna', 'o': 'orange'}, 'g': ['grape', 'grapefruit']}
38 >>> print dict2
39 {'a': ('apple',), 'bo': {'b': 'banna', 'o': 'orange'}, 'g': ['grape', 'grapefruit']}
40 >>> dict["g"][0] = "shuaige"   #修改第二層數據
41 >>> print dict
42 {'a': ('apple',), 'bo': {'b': 'banna', 'o': 'orange'}, 'g': ['shuaige', 'grapefruit']}
43 >>> print dict2
44 {'a': ('apple',), 'bo': {'b': 'banna', 'o': 'orange'}, 'g': ['grape', 'grapefruit']}
45 >>> id(dict["g"][0]),id(dict2["g"][0])
46 (140422980580816, 140422980580288)  #從這里看到第二個數據現在也不是公用了
47 
48 # 通過這里可以看出他們現在是一個完全獨立的,當你修改dict時dict2是不會改變的因為是兩個獨立的字典!

轉載于:https://www.cnblogs.com/FWF1944/p/10878324.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/164060.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息