假設你去面試 Python 開發崗,面試官如果對基礎比較看重的話,那麼很可能會問你這樣的問題
「談談你對 Python 中的淺拷貝和深拷貝的理解?」
若平時你在開發中過度使用 deepcopy,以至於忘記了淺拷貝(shallow copy)和深拷貝(deep copy)的區別,那很可能要栽大跟頭了。
本文轉載一篇小吉大佬的文章,幫助大家更好的理解深拷貝和淺拷貝的區別。
建議在讀這篇文章之前,看下原作者之前寫的文章《你真的理解Python中的賦值、傳參嗎?》,它有助於你更快的理解本文
首先我們要知道,Python 內不可變對象的內存管理方式是引用計數。因此,我們在談論拷貝時,其實談論的主要特點都是基於可變對象的。我們來看下面這段代碼
輸出如下
因為我們這裡操作的是不可變對象,Python 用引用計數的方式管理它們,所以 Python 不會對值相同的不可變對象,申請單獨的內存空間。只會記錄它的引用次數
我們先來比較一下淺拷貝和賦值在可變對象上的區別
輸出結果
發現沒有,賦值就是對物體進行貼標籤操作,作用於同一物體。而淺拷貝則會創建一個新的對象,至於對象中的元素,它依然會引用原來的物體,我們再來看一段例子
輸出如下
操作不可變對象時,由於引用計數的特性,被拷貝的元素改變時,就相當於撕掉了原來的標籤,重新貼上新的標籤一樣,對於我們已拷貝的元素沒有任何影響。因此在操作不可變對象時,淺拷貝和深拷貝是沒有區別的
輸出結果
由於淺拷貝會使用原始元素的引用(內存地址)。所以在在操作被拷貝對象內部的可變元素時,其結果是會影響到拷貝對象的
深拷貝遇到可變對象,則又會進行一層對象創建,所以你操作被拷貝對象內部的可變對象,不影響拷貝對象內部的值
輸出如下
總結
因此,在下次我們遇到這類問題時,我們說出以下關鍵點,基本就很穩了
由於 Python 內部引用計數的特性,對於不可變對象,淺拷貝和深拷貝的作用是一致的,就相當於複製了一份副本,原對象內部的不可變對象的改變,不會影響到複製對象
淺拷貝的拷貝。其實是拷貝了原始元素的引用(內存地址),所以當拷貝可變對象時,原對象內可變對象的對應元素的改變,會在複製對象的對應元素上,有所體現
深拷貝在遇到可變對象時,又在內部做了新建了一個副本。所以,不管它內部的元素如何變化,都不會影響到原來副本的可變對象
圖解 Python 中賦值、淺拷貝、深拷貝的區別
Python中 copy, deepcopy 的區別及原因
崔慶才
靜覓博客博主,《Python3網絡爬蟲開發實戰》作者
隱形字
個人公眾號:進擊的Coder