當前位置:成語大全網 - 新華字典 - Python對象的拷貝

Python對象的拷貝

Python賦值操作或函數參數傳遞,傳遞的永遠是對象引用(即內存地址),而不是對象內容。在Python中壹切皆對象,對象又分為可變(mutable)和不可變(immutable)兩種類型。對象拷貝是指在內存中創建新的對象,產生新的內存地址。當頂層對象和它的子元素對象全都是immutable不可變對象時,不存在被拷貝,因為沒有產生新對象。淺拷貝(Shallow Copy),拷貝頂層對象,但不會拷貝內部的子元素對象。深拷貝(Deep Copy),遞歸拷貝頂層對象,以及它內部的子元素對象。

Python中壹切皆對象,對象就像壹個塑料盒子, 裏面裝的是數據。對象有不同類型,例如布爾型和整型,類型決定了可以對它進行的操作。現實生活中的"陶器"會暗含壹些信息(例如它可能很重且易碎,註意不要掉到地上)。

對象的類型還決定了它裝著的數據是允許被修改的變量(可變的mutable)還是不可被修改的常量(不可變的immutable)。妳可以把不可變對象想象成壹個透明但封閉的盒子:妳可以看到裏面裝的數據,但是無法改變它。類似地,可變對象就像壹個開著口的盒子,妳不僅可以看到裏面的數據,還可以拿出來修改它,但妳無法改變這個盒子本身,即妳無法改變對象的類型。

對象拷貝是指在內存中創建新的對象,產生新的內存地址。

淺拷貝(Shallow Copy),拷貝頂層對象,但不會拷貝內部的子元素對象。

2.1.1. 頂層是mutable,子元素全是immutable

當頂層對象是mutable可變對象,但是它的子元素對象全都是immutable不可變對象時,如[1, 'world', 2]

① 創建列表對象並賦值給變量a

② 導入copy模塊,使用copy.copy()函數淺拷貝a,並賦值給變量b

③ 修改變量a的子元素a[0] = 3,由於整數是不可變對象,所以並不是修改1變為3,而是更改a[0]指向對象3

當頂層對象是 mutable可變對象 ,但子元素也存在 mutable可變對象 時,如 [1, 2, ['hello','world']]

① 淺拷貝 copy.copy() 只拷貝了頂層對象,沒有拷貝子元素對象['hello','world'],即a[2]和b[2]指向同壹個列表對象

② 修改a[2][1] = 'china',則b[2][1] = 'china'

當頂層對象是immutable不可變對象,同時它的子元素對象也全都是immutable不可變對象時,如(1, 2, 3)

變量a與變量b指向的是同壹個元組對象,沒有拷貝

當頂層對象是immutable不可變對象時,但子元素存在mutable可變對象時,如(1, 2, ['hello','world'])

變量a與變量b指向的是相同的元組對象,並且a[2]與b[2]指向同壹個列表,所以修改a[2][1]會影響b[2][1]

深拷貝(Deep Copy),遞歸拷貝頂層對象,以及它內部的子元素對象

當頂層對象是mutable可變對象,但是它的子元素對象全都是immutable不可變對象時,如[1, 'world', 2]

變量a與變量b指向不同的列表對象,修改a[0]只是將列表a的第壹個元素重新指向新對象,不會影響b[0]

當頂層對象是mutable可變對象,但子元素也存在mutable可變對象時,如[1, 2, ['hello','world']]

深拷貝既拷貝了頂層對象,又遞歸拷貝了子元素對象,所以a[2]與b[2]指向了兩個不同的列表對象(但是列表對象的子元素初始指定的字符串對象壹樣),修改a[2][1] = 'china'後,它重新指向了新的字符串對象(內存地址為140531581905808),不會影響到b[2][1]

當頂層對象是immutable不可變對象,同時它的子元素對象也全都是immutable不可變對象時,如(1, 2, 3)

變量a與變量b指向的是同壹個元組對象,不存在拷貝

當頂層對象是immutable不可變對象時,但子元素存在mutable可變對象時,如(1, 2, ['hello','world'])

變量a與變量b指向的是不同的元組對象,同時a[2]與b[2]指向不同的列表對象,所以修改a[2][1]不會影響b[2][1]

使用=是賦值,即將列表對象的引用也賦值給變量b,可以將列表對象想像成壹個盒子,變量a相當於這個盒子上的標簽,執行b = a後,相當於再在這個盒子上貼上b標簽,a和b實際上指向的是同壹個對象。因此,無論我們是通過a還是通過b來修改列表的內容,其結果都會作用於雙方。

b/c/d都是a的復制,它們都指向了不同的列表對象,但是沒有拷貝子元素,a[2]和b[2]/c[2]/d[2]指向同壹個列表, 相當於淺拷貝的效果

使用分片[:]操作,a和b其實是指向同壹個元組,而且沒有拷貝子元素,a[2]和b[2]也指向同壹個列表,相當於淺拷貝的效果

同列表類似,可以使用字典的copy()函數或者轉換函數dict()

變量a與變量b/c指向不同的字典,但是沒有拷貝子元素,a['jobs']和b['jobs']/c['jobs']指定同壹個列表, 相當於淺拷貝的效果

同列表類似,可以使用集合的copy()函數或者轉換函數set()

變量a與變量b/c指向不同的集合,而集合的元素必須是hashable,所以修改集合a不會影響到b/c