python中的深淺拷貝


python 中的深淺復制

前言

想起來寫這篇博客是因為這段時間學習 js 的時候涉及到了變量的深淺復制問題,然后想先把 python 中的深淺復制理解的更深入一些,再寫 js 中的深淺復制,因為 python 對我來說已經很熟悉了。

在 python 中,標識一個對象的唯一身份有三個狀態:對象的 id(內存地址),對象類型,對象值。

賦值

  • 賦值是將一個對象的地址賦值給一個變量,使得變量指向該內存地址;
  • 修改不可變對象時(str、tuple、int)需要開辟新的內存空間;
  • 修改可變對象時(list、dict、set)不需要開辟新的內存空間。

賦值是將 id 重新賦值給了一個新的變量,引用計數加1。

淺拷貝

淺拷貝只是拷貝父對象,而對於父對象中的子對象並不會進行拷貝。

a = {1: [1, 2, 3]}
b = a.copy()
a['name'] = 'musibii'
a # {1: [1, 2, 3], 'name': 'musibii'}
b # {1: [1, 2, 3]}
a[1].append(4)
a # {1: [1, 2, 3, 4], 'name': 'musibii'}
b # {1: [1, 2, 3, 4]}

也就是說淺拷貝將a的值復制到一個新的內存空間,並將內存地址賦值給 b,所以對 a 對象添加新的屬性,b 並不會改變;但是因為淺拷貝只是拷貝了一層,對於子對象的內存空間是原對象的內存引用,所以修改 a 相應的 b 中也會改變。

淺拷貝只拷貝父對象,不會拷貝對象內部的子對象。

深拷貝

深拷貝完全賦值被復制對象的元素,不是復制內存地址,是開辟新的內存空間將被復制對象的值放在了新的內存空降中,並將新的內存地址指向了新的變量,這樣的話,修改原對象不會對新的對象產生影響。

深拷貝是在另一塊地址中創建一個新的變量,同時容器內的元素的地址也是新開辟的,僅僅是值相同而已,是完全的副本。

在Python 中深拷貝需要引入 copy 模塊:

import copy
c = copy.deepcopy(a)
c # {1: [1, 2, 3], 'name': 'musibii'}
a[1].append(4)
a # {1: [1, 2, 3, 4], 'name': 'musibii'}
c # {1: [1, 2, 3], 'name': 'musibii'}

解析

  1. b = a:賦值引用,a 和 b 都指向同一個對象

  1. b = a.copy():淺拷貝,a 和 b 是一個獨立的對象,但他們的子對象還是指向同一個對象(引用)。

  1. b = copy.deepcopy(a):深拷貝,a 和 b 完全拷貝了父對象及其子對象,兩者完全獨立。

更多實例

import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始對象
 
b = a                       #賦值,傳對象的引用
c = copy.copy(a)            #對象拷貝,淺拷貝
d = copy.deepcopy(a)        #對象拷貝,深拷貝
 
a.append(5)                 #修改對象a
a[4].append('c')            #修改對象a中的['a', 'b']數組對象
 
print( 'a = ', a )
print( 'b = ', b )
print( 'c = ', c )
print( 'd = ', d )

輸出

('a = ', [1, 2, 3, 4, ['a', 'b', 'c'], 5])
('b = ', [1, 2, 3, 4, ['a', 'b', 'c'], 5])
('c = ', [1, 2, 3, 4, ['a', 'b', 'c']])
('d = ', [1, 2, 3, 4, ['a', 'b']])

以上部分參考

菜鳥教程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM