python深拷貝和淺拷貝之簡單分析

來源:互聯網
上載者:User

標籤:str   需要   append   為什麼   ruby   --   而不是   list   第一個   

title: python 深拷貝和淺拷貝
tags: python,copy,deepcopy
grammar_cjkRuby: true
---

python 深拷貝和淺拷貝

python的變數的賦值都是引用
把一個變數賦值給一個變數,不是拷貝這個對象,而是拷貝這個變數的引用

  1. 直接賦值

    傳遞的是這個變數的引用

  2. 淺拷貝

    拷貝的是這個變數的引用,會產生新的對象
    淺拷貝會產生一個新的對象,但是淺拷貝的內容還是原有對象的引用
    看下面的例子

淺拷貝
import copya = [1, 2, 3, 4 ,5]b = copy.copy(a)print id(a)140637017675968print id(b)140637017452416print [id(item) for item in a][30363992, 30363968, 30363944, 30363920, 30363896]print [id(item) for item in b] [30363992, 30363968, 30363944, 30363920, 30363896]

我們可以看到,copy.copy這個淺拷貝的操作,產生了一個新的對象
因此,id(a) ,id(b)是不同的
但是,淺拷貝對於所拷貝對象中的各個元素,只會使用這些元素的引用,並不會再繼續產生新的對象
所以,兩者各個元素的id是相同的

再看個淺拷貝的例子

import copya = [1, 2, 3, 4 ,5]b = copy.copy(a)print id(a)140337638905904print id(b)140337638904824a.append(6)print a[1, 2, 3, 4, 5, 6]print id(a)140337638905904print b[1, 2, 3, 4, 5]print id(b)140337638904824

可以看到,因為淺拷貝也是建立了一個新的對象,所以a 和 a的淺拷貝b,是兩個不同的對象
所以給對象aj添加元素,並不會對b產生影響

再來看一個淺拷貝的例子 這個淺拷貝的例子對於其拷貝的對象也產生了影響,為什麼呢?

import copy a = [1, 2, 3, [1]]print id(a)140063950885808b = copy.copy(a)print id(b)140063949633512print [id(item) for item in a][29266264, 29266240, 29266216, 140063949688416]print [id(item) for item in b][29266264, 29266240, 29266216, 140063949688416]a[3].append(2)print a[1, 2, 3, [1, 2]] print b[1, 2, 3, [1, 2]]

可以看到,這個例子中,a對象和其拷貝產生的對象b
首先,淺拷貝,建立了一個對象b
a 和 b是兩個不同的對象
由於淺拷貝,建立的對象b的各個元素其實是原對象a的各個元素的引用(這是和上一個例子不同的地方,上一個例子是原有對象新增了一個元素)
這個例子是原有對象對於其最後一個元素(也是清單類型)新增了一個元素
因為 a 和b 兩個對象的各個元素其實是一樣的(b的各個元素其實是a的各個元素的引用),所以a 的某個元素的變化會讓b一樣的變化

我們再看一個淺拷貝的例子

import copya = [1, 2, 3, [1]]print id(a)140063950885808b = copy.copy(a)print id(b)140063949633512print [id(item) for item in a][29266264, 29266240, 29266216, 140063949688416]print [id(item) for item in b][29266264, 29266240, 29266216, 140063949688416]a[3].append(2)print a[1, 2, 3, [1, 2]]print b[1, 2, 3, [1, 2]]a[0] = 10a[10, 2, 3, [1, 2]]b[1, 2, 3, [1, 2]]print [id(item) for item in a][29266048, 29266240, 29266216, 140063949688416]print [id(item) for item in b][29266264, 29266240, 29266216, 140063949688416]

前面的操作都沒毛病,怎麼最後對於對象a的第一個元素的操作讓a變化了,卻沒有影響到b呢?
這是因為操作的a的第一個元素是int類型,這是不可變對象,對於不可變對象的重新賦值本質上是建立一個新的對象
所以,其實這樣操作後a的第一個元素對應的對象已經不是原來的對象了,當然不會影響到b

深拷貝
import copya = [1, 2, 3, 4, [1]]b = copy.deepcopy(a)print [id(item) for item in a][40378712, 40378688, 40378664, 40378640, 140313123501048]print [id(item) for item in b][40378712, 40378688, 40378664, 40378640, 140313122753568]a[4].append(2)a[1, 2, 3, 4, [1, 2]]b[1, 2, 3, 4, [1]]

在上面,我們可以看到,深拷貝,對於a 的 a[4] 即一個可變對象(list類型)而言,是產生了一個新的對象,而不是像淺拷貝一樣,只是原對象元素的引用
因此,原對象的變化,不會引起拷貝對象的變化

總結:
對於淺拷貝,深拷貝來說,如果拷貝對象的元素是不可變類型(或者說不可變對象)
則無論淺拷貝,深拷貝,對原有對象的改變,都不會影響到拷貝的對象的這個元素
因為,不可變類型的更改,其實是建立了一個對象,自然不會影響到原有對象
當被拷貝對象含有可變類型的元素的時候,對於原有對象的這個可變類型的元素的更改:
淺拷貝,會影響到被拷貝對象
深拷貝,不會影響到被拷貝對象,因為深拷貝對於不可變類型的元素,是產生了一個新的對象來複製這個元素的
所以,如果希望複製一份原有對象,不被影響,需要使用深拷貝

python深拷貝和淺拷貝之簡單分析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.