5 張圖徹底理解 Python 中的淺拷貝與深拷貝

2021-02-19 進擊的Coder

假設你去面試 Python 開發崗,面試官如果對基礎比較看重的話,那麼很可能會問你這樣的問題

「談談你對 Python 中的淺拷貝和深拷貝的理解?」

若平時你在開發中過度使用 deepcopy,以至於忘記了淺拷貝(shallow copy)和深拷貝(deep copy)的區別,那很可能要栽大跟頭了。

本文轉載一篇小吉大佬的文章,幫助大家更好的理解深拷貝和淺拷貝的區別。

建議在讀這篇文章之前,看下原作者之前寫的文章《你真的理解Python中的賦值、傳參嗎?》,它有助於你更快的理解本文


Python 的引用計數

首先我們要知道,Python 內不可變對象的內存管理方式是引用計數。因此,我們在談論拷貝時,其實談論的主要特點都是基於可變對象的。我們來看下面這段代碼



輸出如下


因為我們這裡操作的是不可變對象,Python 用引用計數的方式管理它們,所以 Python 不會對值相同的不可變對象,申請單獨的內存空間。只會記錄它的引用次數


淺拷貝

我們先來比較一下淺拷貝和賦值在可變對象上的區別


輸出結果

發現沒有,賦值就是對物體進行貼標籤操作,作用於同一物體。而淺拷貝則會創建一個新的對象,至於對象中的元素,它依然會引用原來的物體,我們再來看一段例子


輸出如下



操作不可變對象時,由於引用計數的特性,被拷貝的元素改變時,就相當於撕掉了原來的標籤,重新貼上新的標籤一樣,對於我們已拷貝的元素沒有任何影響。因此在操作不可變對象時,淺拷貝和深拷貝是沒有區別的


輸出結果

由於淺拷貝會使用原始元素的引用(內存地址)。所以在在操作被拷貝對象內部的可變元素時,其結果是會影響到拷貝對象的


深拷貝

深拷貝遇到可變對象,則又會進行一層對象創建,所以你操作被拷貝對象內部的可變對象,不影響拷貝對象內部的值


輸出如下

總結

因此,在下次我們遇到這類問題時,我們說出以下關鍵點,基本就很穩了

由於 Python 內部引用計數的特性,對於不可變對象,淺拷貝和深拷貝的作用是一致的,就相當於複製了一份副本,原對象內部的不可變對象的改變,不會影響到複製對象

淺拷貝的拷貝。其實是拷貝了原始元素的引用(內存地址),所以當拷貝可變對象時,原對象內可變對象的對應元素的改變,會在複製對象的對應元素上,有所體現

深拷貝在遇到可變對象時,又在內部做了新建了一個副本。所以,不管它內部的元素如何變化,都不會影響到原來副本的可變對象


參考資料

圖解 Python 中賦值、淺拷貝、深拷貝的區別

Python中 copy, deepcopy 的區別及原因

崔慶才

靜覓博客博主,《Python3網絡爬蟲開發實戰》作者

隱形字

個人公眾號:進擊的Coder

相關焦點

  • 低門檻徹底理解JavaScript中的深拷貝和淺拷貝
    在說深拷貝與淺拷貝前,我們先看兩個簡單的案例:按照常規思維,obj1應該和num1一樣,不會因為另外一個值的改變而改變,而這裡的obj1 卻隨著obj2的改變而改變了。同樣是變量,為什麼表現不一樣呢?再回到前面的案例,案例1中的值為基本類型,案例2中的值為引用類型。案例2中的賦值就是典型的淺拷貝,並且深拷貝與淺拷貝的概念只存在於引用類型。
  • 面試題-python 淺拷貝和深拷貝(copy模塊)
    前言面試的時候經常會問到深拷貝和淺拷貝,那麼python的深拷貝和淺拷貝有什麼區別呢?這裡有個知識點:在python中,都是將「對象的引用(內存地址)」賦值給變量的。其次,在python中有6個標準數據類型,他們分為可變和不可變兩類。可變和不可變對象在python中有6個標準數據類型,他們分為可變和不可變兩類。
  • 深拷貝和淺拷貝之list、dataframe
    python list:b = a是淺拷貝,b = list(a)和b = copy.cpoy(a)是深拷貝。淺拷貝,a和b指向的是一個地址。當b改變後,a也會改變。深拷貝,a和b指向的是兩個地址,當b改變後,a不受影響。
  • Python深拷貝和淺拷貝詳解
    對於淺拷貝(shallow copy)和深度拷貝(deep copy),本節並不打算一上來拋出它們的概念,而是先從它們的操作方法說起,通過代碼來理解兩者的不同
  • 前端面試-深拷貝和淺拷貝
    面試題目:如何實現對一個數組或對象的淺拷貝和深拷貝?WTF,複製還分兩種,第一次遇到這種問題的時候很是無語呢,先來看看一般的答案的理解。淺拷貝是只拷貝一層,深層次的對象級別就只拷貝引用。 深拷貝是拷貝多層,每一級別的數據都拷貝出來。
  • 一文讀懂 javascript 深拷貝與淺拷貝
    讀完本文,希望你能明白:淺拷貝與深拷貝淺拷貝是創建一個新對象,這個對象有著原始對象屬性值的一份精確拷貝。如果屬性是基本類型,拷貝的就是基本類型的值,如果屬性是引用類型,拷貝的就是內存地址 ,所以如果其中一個對象改變了這個地址,就會影響到另一個對象。
  • 圖解 Python 中深淺拷貝(copy)
    為了生成這個副本,就產生了拷貝。今天就說一下Python中的深淺拷貝問題。但是python對深copy做了一個優化,將可變的數據類型在內存中重新創建一份,而不可變的數據類型則沿用之前的,所以內存中是下面這樣的:
  • JavaScript系列--如何優雅簡單的實現深拷貝和淺拷貝
    優雅簡單的實現深拷貝和淺拷貝淺析JavaScript解析賦值、淺拷貝和深拷貝的區別:裡面介紹了解析賦值,淺拷貝,深拷貝的原理和實現。淺拷貝方法:Object.assign(),展開語法Spread,Array.prototype.alice(),array.prototype.concat()。深拷貝方法:JSON.parse(JSON.stringify(object)),對於undefined,symbol和函數的會直接忽略。
  • JavaScript的深拷貝實現
    在實際開發當中,我們經常會遇到要對對象進行深拷貝的情況。而且深拷貝這個問題在面試過程中也經常會遇到,下面就對本人在學習過程中的收穫,做以簡單的總結。什麼是淺拷貝,什麼是深拷貝?什麼是淺拷貝關於淺拷貝的概念,我在網上看到一種說法,直接上代碼。
  • C++之拷貝構造函數的淺copy和深copy
    :(1)淺拷貝拷貝後對象的物理狀態相同(2)深拷貝拷貝後對象的邏輯狀態相同5、什麼時候需要進行深拷貝?注意:一般來說,自定義拷貝構造函數(也就是我們自己手寫的),必然需要實現深拷貝!對象的拷貝有淺拷貝和深拷貝兩種方式。
  • 看看你知道的「淺拷貝」是對的嗎
    ,在應聘者的回答中,筆者發現有好一部分人對淺拷貝都是錯誤的,故有了此篇內容。她: 「複製對象有深拷貝和淺拷貝...」大佬:」說一下這兩者之間的區別「她: 」我給你寫一段淺拷貝的代碼「var a = { x: 1 };var b = a;大佬:」回去等通知吧 ~.~「2.
  • 一篇文章讀懂Python賦值與拷貝
    通過x2 修改對象時,x3 也會跟著變化,因為本質上它們是同一個對象,這就好比張三和小張是同一個人時,給張三添衣服其實就是給小張添衣服。拷貝又分為淺拷貝和深拷貝。>>> s == sc == sdc True>>> s is sc False>>> s is sdcFalse那麼淺拷貝(shallow copy)與深拷貝(deep copy)有什麼區別呢?
  • 深淺拷貝知多少?
    (主要是包括數組對象和object對象)如下圖所示:實現方式淺拷貝的實現方式 以上了解了數據類型的存儲和拷貝的基礎概念,來具體看一下哪一些情況,賦值、拷貝是可以完全獨立存在的,哪一些情況是會改變到原有對象的內容的。請看:按照淺拷貝的基礎概念,寫了一個shallowCopy的方法,並且拷貝後同樣改變原數據中的元素,如下:
  • 什麼是Java深淺拷貝?
    拷貝與Java內存結構息息相關,搞懂Java深淺拷貝是很必要的!在對象的拷貝中,很多初學者可能搞不清到底是拷貝了引用還是拷貝了對象。在拷貝中這裡就分為引用拷貝、淺拷貝、深拷貝進行講述。引用拷貝引用拷貝會生成一個新的對象引用地址,但是兩個最終指向依然是同一個對象。如何更好的理解引用拷貝呢?
  • Pandas和Numpy的視圖和拷貝
    在Numpy和Pandas中,有兩個重要概念,容易混淆,一個是淺拷貝,也稱為視圖,另外一個是深拷貝,或者就稱為拷貝。如果操作不當,Pandas會爆出SettingWithCopyWarning的異常。本文我將就視圖和拷貝問題,結合異常進行總結。
  • 深拷貝的終極探索(90%的人都不了解)
    ,由淺入深,環環相扣,總共涉及4種深拷貝方式,每種方式都有自己的特點和個性深拷貝 VS 淺拷貝再開始之前需要先給同學科普下什麼是深拷貝,和深拷貝有關係的另個一術語是淺拷貝又是什麼意思呢?如果對這部分部分內容了解的同學可以跳過其實深拷貝和淺拷貝都是針對的引用類型,JS中的變量類型分為值類型(基本類型)和引用類型;對值類型進行複製操作會對值進行一份拷貝,而對引用類型賦值,則會進行地址的拷貝,最終兩個變量指向同一份數據// 基本類型var a = 1;var b = a;a = 2;console.log(a, b); // 2, 1 ,a b指向不同的數據
  • Java 拷貝,你能說出個 123 麼?
    作者 | sowhat1412 責編 | 張文頭圖 | CSDN 下載自視覺中國本文主要講解:對象創建方式、Java中的深拷貝和淺拷貝。本次講解的是 Java 的深拷貝和淺拷貝,其實現方式正是通過調用 Object 類的 clone() 方法來完成。
  • 面試題:如何實現一個深拷貝
    ,並對其進行了模擬實現,在實現的過程中,介紹了很多基礎知識。今天這篇文章我們來看看一道必會面試題,即如何實現一個深拷貝。第一步:簡單實現其實深拷貝可以拆分成 2 步,淺拷貝 + 遞歸,淺拷貝時判斷屬性值是否是對象,如果是對象就進行遞歸操作,兩個一結合就實現了深拷貝。根據上篇文章內容,我們可以寫出簡單淺拷貝代碼如下。
  • 面試官:老是問我深淺拷貝問題,自己看文章
    從上面兩張圖,我們可以知道:淺拷貝:比如我們定義一個變量為 obj 的對象,然後我們把他賦值給另一個變量,這個過程就會涉及到淺拷貝問題,另一個變量只是之前變量的一份拷貝,前後兩個變量的存儲地址是公用的 obj.name) // true 說明使用同一個引用地址let str = "Ken"let str1 = strconsole.log(str === str1) // true 但是只是拷貝了值深拷貝你可這麼理解,就比如我們將衣服放在一個衣櫃裡面
  • Python中如何拷貝一個文件
    # 文件的拷貝import osimport shutil# os system()拷貝