首頁技術(shù)文章正文

Python中的深拷貝和淺拷貝

更新時(shí)間:2022-10-14 來源:黑馬程序員 瀏覽量:

1. 淺拷貝

copy函數(shù)是淺拷貝,只對可變類型的第一層對象進(jìn)行拷貝,對拷貝的對象開辟新的內(nèi)存空間進(jìn)行存儲,不會拷貝對象內(nèi)部的子對象。不可變類型的淺拷貝示例代碼:

import copy  # 使用淺拷貝需要導(dǎo)入copy模塊

# 不可變類型有: 數(shù)字、字符串、元組

a1 = 123123
b1 = copy.copy(a1)  # 使用copy模塊里的copy()函數(shù)就是淺拷貝了
# 查看內(nèi)存地址
print(id(a1))
print(id(b1))

print("-" * 10)
a2 = "abc"
b2 = copy.copy(a2)
# 查看內(nèi)存地址
print(id(a2))
print(id(b2))

print("-" * 10)
a3 = (1, 2, ["hello", "world"])
b3 = copy.copy(a3)
# 查看內(nèi)存地址
print(id(a3))
print(id(b3))

運(yùn)行上述程序的結(jié)果如下:

140459558944048
140459558944048
----------
140459558648776
140459558648776
----------
140459558073328
140459558073328

不可變類型的淺拷貝說明:

通過上面的執(zhí)行結(jié)果可以得知,不可變類型進(jìn)行淺拷貝不會給拷貝的對象開辟新的內(nèi)存空間,而只是拷貝了這個對象的引用。

可變類型的淺拷貝示例代碼:

import copy # 使用淺拷貝需要導(dǎo)入copy模塊

# 可變類型有: 列表、字典、集合

a1 = [1, 2]
b1 = copy.copy(a1) # 使用copy模塊里的copy()函數(shù)就是淺拷貝了
# 查看內(nèi)存地址
print(id(a1))
print(id(b1))
print("-" * 10)
a2 = {"name": "張三", "age": 20}
b2 = copy.copy(a2)
# 查看內(nèi)存地址
print(id(a2))
print(id(b2))
print("-" * 10)
a3 = {1, 2, "王五"}
b3 = copy.copy(a3)
# 查看內(nèi)存地址
print(id(a3))
print(id(b3))

print("-" * 10)
a4 = [1, 2, [4, 5]]
# 注意:淺拷貝只會拷貝父對象,不會對子對象進(jìn)行拷貝
b4 = copy.copy(a4) # 使用copy模塊里的copy()函數(shù)就是淺拷貝了
# 查看內(nèi)存地址
print(id(a4))
print(id(b4))
print("-" * 10)
# 查看內(nèi)存地址
print(id(a4[2]))
print(id(b4[2]))

# 修改數(shù)據(jù)
a4[2][0] = 6

# 子對象的數(shù)據(jù)會受影響
print(a4)
print(b4)

運(yùn)行結(jié)果:

139882899585608
139882899585800
----------
139882919626432
139882919626504
----------
139882919321672
139882899616264
----------
139882899587016
139882899586952
----------
139882899693640
139882899693640
[1, 2, [6, 5]]
[1, 2, [6, 5]]

可變類型的淺拷貝說明:

通過上面的執(zhí)行結(jié)果可以得知,可變類型進(jìn)行淺拷貝只對可變類型的第一層對象進(jìn)行拷貝,對拷貝的對象會開辟新的內(nèi)存空間進(jìn)行存儲,子對象不進(jìn)行拷貝。

2. 深拷貝

deepcopy函數(shù)是深拷貝, 只要發(fā)現(xiàn)對象有可變類型就會對該對象到最后一個可變類型的每一層對象就行拷貝, 對每一層拷貝的對象都會開辟新的內(nèi)存空間進(jìn)行存儲。

不可變類型的深拷貝示例代碼:

import copy  # 使用深拷貝需要導(dǎo)入copy模塊

# 不可變類型有: 數(shù)字、字符串、元組

a1 = 1
b1 = copy.deepcopy(a1)  # 使用copy模塊里的deepcopy()函數(shù)就是深拷貝了
# 查看內(nèi)存地址
print(id(a1))
print(id(b1))
print("-" * 10)
a2 = "張三"
b2 = copy.deepcopy(a2)
# 查看內(nèi)存地址
print(id(a2))
print(id(b2))
print("-" * 10)
a3 = (1, 2)
b3 = copy.deepcopy(a3)
# 查看內(nèi)存地址
print(id(a3))
print(id(b3))
print("-" * 10)

# 注意: 元組里面要是有可變類型對象,發(fā)現(xiàn)對象有可變類型就會該對象到最后一個可變類型的每一層對象進(jìn)行拷貝
a4 = (1, ["李四"])
b4 = copy.deepcopy(a4)
# 查看內(nèi)存地址
print(id(a4))
print(id(b4))
# 元組里面的可變類型子對象也會進(jìn)行拷貝
print(id(a4[1]))
print(id(b4[1]))

運(yùn)行結(jié)果:

9289120
9289120
----------
140115621848320
140115621848320
----------
140115621859592
140115621859592
----------
140115602480584
140115621834568
140115602328136
140115602436168

不可變類型的深拷貝說明:

通過上面的執(zhí)行結(jié)果可以得知:

不可變類型進(jìn)行深拷貝如果子對象沒有可變類型則不會進(jìn)行拷貝,而只是拷貝了這個對象的引用,否則會對該對象到最后一個可變類型的每一層對象就行拷貝, 對每一層拷貝的對象都會開辟新的內(nèi)存空間進(jìn)行存儲

可變類型的深拷貝示例代碼:

import copy  # 使用深拷貝需要導(dǎo)入copy模塊

# 可變類型有: 列表、字典、集合

a1 = [1, 2]
b1 = copy.deepcopy(a1)  # 使用copy模塊里的deepcopy()函數(shù)就是深拷貝了
# 查看內(nèi)存地址
print(id(a1))
print(id(b1))
print("-" * 10)
a2 = {"name": "張三"}
b2 = copy.deepcopy(a2)
# 查看內(nèi)存地址
print(id(a2))
print(id(b2))
print("-" * 10)
a3 = {1, 2}
b3 = copy.deepcopy(a3)
# 查看內(nèi)存地址
print(id(a3))
print(id(b3))
print("-" * 10)

a4 = [1, 2, ["李四", "王五"]]
b4 = copy.deepcopy(a4)  # 使用copy模塊里的deepcopy()函數(shù)就是深拷貝了
# 查看內(nèi)存地址
print(id(a4))
print(id(b4))

# 查看內(nèi)存地址
print(id(a4[2]))
print(id(b4[2]))
a4[2][0] = "王五"
# 因?yàn)榱斜淼膬?nèi)存地址不同,所以數(shù)據(jù)不會收到影響
print(a4)
print(b4)

運(yùn)行結(jié)果:

140348291721736
140348291721928
----------
140348311762624
140348311221592
----------
140348311457864
140348291752456
----------
140348291723080
140348291723144
140348291723208
140348291723016
[1, 2, ['王五', '王五']]
[1, 2, ['李四', '王五']]

可變類型的深拷貝說明:

通過上面的執(zhí)行結(jié)果可以得知, 可變類型進(jìn)行深拷貝會對該對象到最后一個可變類型的每一層對象就行拷貝, 對每一層拷貝的對象都會開辟新的內(nèi)存空間進(jìn)行存儲。

不管是給對象進(jìn)行深拷貝還是淺拷貝,只要拷貝成功就會開辟新的內(nèi)存空間存儲拷貝的對象。淺拷貝和深拷貝的區(qū)別是:淺拷貝最多拷貝對象的一層,深拷貝可能拷貝對象的多層。


分享到:
在線咨詢 我要報(bào)名
和我們在線交談!