欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談Python淺拷貝、深拷貝及引用機制

 更新時間:2016年12月15日 14:42:20   作者:bestallen  
本篇文章主要介紹了Python淺拷貝、深拷貝及引用機制,詳細的介紹了淺拷貝、深拷貝的介紹和區(qū)別,有興趣的可以了解一下。

這禮拜碰到一些問題,然后意識到基礎(chǔ)知識一段時間沒鞏固的話,還是有遺忘的部分,還是需要溫習,這里做份筆記,記錄一下

前續(xù)

先簡單描述下碰到的題目,要求是寫出2個print的結(jié)果

可以看到,a指向了一個列表list對象,在Python中,這樣的賦值語句,其實內(nèi)部含義是指a指向這個list所在內(nèi)存地址,可以看作類似指針的概念。

而b,注意,他是把a對象包裹進一個list,并且乘以5,所以b的樣子應(yīng)該是一個大list,里面元素都是a

而當a對象進行了append操作后,其實,隱含的意思是,內(nèi)存中的這個list進行了修改,所有對此對象進行引用的對象,都會發(fā)生改變

我將a的id打印出來,并且,同時打印b這個對象中所包含的元素a的id,這樣可以看到,在b這個list中,每個元素的id,和a是一樣的

我們可以看到,a對象的id(內(nèi)存地址)為10892296,雖然b把a包裹進了新的list,但是,這個元素引用的,還是相同地址的對象,可以用下圖來解釋

之后,我們對a進行了append操作,由于list是一個可變對象,所以,他的內(nèi)存地址并沒有改變,但是,對于內(nèi)存中這個地址的引用的所有對象,都會被一同改變可以從上面測試圖分割線下半部分看出來.

由此,引出了對Python引用機制和淺復制及深復制的復習

Python的引用機制

引用機制案例1

由上面的例子,我們可以看到,python的引用傳遞,最終結(jié)果是讓2個對象都引用內(nèi)存中同一塊區(qū)域的內(nèi)容

所以我們來看一下下面的例子

B通過A,同樣引用了id為17446024的地址的內(nèi)容,2者的id(內(nèi)存地址)都是一毛一樣的

所以,通過A的操作  A[0]=3  或是   A[3].append(6)  ,都會對這塊內(nèi)存中的內(nèi)容進行修改(因為list是可變對象,所以內(nèi)存地址并不會改變,這個后面再講)

這個是最基本的引用案例 (另外說句,由于A和B都指向了同一塊內(nèi)存地址,所以通過B修改的內(nèi)容,也能反映到A上面去)

引用機制案例2

我們再來看一個案例

看題目貌似是會把元素2替換成本身這個列表,結(jié)果也許應(yīng)該是 A=[1,[1,2,3],3]

但其實并不是??!你可以看到,紅框中部分,中間有無限多個嵌套

為什么會這樣呢?

其實是因為,A指向的是[1,2,3]這個列表,在這個例子中,只是把A的第2個元素,指向了A對象本身,所以說,只是A的結(jié)構(gòu)發(fā)生了變化!但是,A還是指向那個對象

我們可以通過打印A的id來看,他的指向是沒有變的!!

來看一下,A的指向并沒有變

那如果我們要達到最后輸出效果是 [1,[1,2,3],3]的效果,應(yīng)該如何來操作呢?

這里,我們就要用到淺復制了,用法可以如下

 

淺復制和深復制

淺復制

現(xiàn)在,就來說說淺復制和深復制,上面的方法實際上只是進行了淺復制,shallow copy,含義是他是對原來引用的對象進行了復制,但是不再引用同一對象地址

看下面的例子,B通過 B = A[:] 操作,來進行了淺復制,你可以看到,淺復制之后,A和B引用的內(nèi)存地址已經(jīng)是不同的了
但是,A和B內(nèi)部的元素的引用地址,還是相同的,這點要非常注意!是有區(qū)別的?。?!

A和B的引用內(nèi)存地址的不同,帶來的效果是,你在B上面進行的操作,并不會影響到A。

淺拷貝歸納:

所以淺拷貝,可以歸納為,復制一份引用,新的對象和原來的對象的引用被區(qū)分開,但是內(nèi)部元素的地址引用還是相同的

但是淺復制也會有問題,問題在哪里呢?就是碰到有嵌套的情況,比如下面的情況可以看到,我給B賦值了一份A的淺復制,這樣A和B的id(內(nèi)存地址)就不一樣了。

所以,當我修改A[0]=8的時候,B不會被影響到,因為他們A和B兩者是獨立的引用,但是這里中間有一個嵌套的列表 [4,5,6]
這個[4,5,6]我們可以理解為:A和B還共同引用著,也就是對于A和B的第二個元素來說,他們還是指向同一塊內(nèi)存地址的。

另外要說一句,由于int是不可變類型,所以,把A[0]修改成8之后,他的引用地址就變了!就和B[0]這個元素的引用區(qū)分開了。

深復制

那如何面對這樣的情況呢?就要用到python模塊里面的copy模塊了

copy模塊有2個功能

1: copy.copy(你要復制的對象) : 這個是淺拷貝,和前面對list進行的 [:] 操作性質(zhì)是一樣的

2: copy.deepcopy(你要復制的對象) : 這個是深拷貝,他除了和淺拷貝一樣,會新生成一份對象的引用,另外對于內(nèi)部的元素,都會新生成引用,以獨立分開.

看下面的例子,當你給B賦值一份A的深復制之后,他倆可以說是完全獨立開了,無論你修改的是A里面的不可變元素,還是修改A里面嵌套的可變元素,結(jié)果都不會影響到B

我的理解是:深復制可以稱之為遞歸拷貝,他會把所有嵌套的可變元素都拷貝一下,然后獨立引用出來.

深復制歸納:

深復制的效果,除了和淺復制一樣,將對象的引用新生成一份引用之外,內(nèi)部所有嵌套的元素,他都會幫你一一獨立開.

自己畫了2張圖,以表示淺復制和深復制的效果區(qū)別

需要說明的是,雖然淺復制之后,列表內(nèi)不可變元素的引用地址還是相同的,但是,正因為他們是不可變元素,所以,其中任意不可變元素被改變之后,引用地址都會是新的,而不會影響到原來的引用地址。

 



總結(jié)

所以,到這里,淺復制和深復制的機制,基本上理解了。

另外還有特殊情況需要說明

對于不可變類型:int, str, tuple, float 這樣的元素來說,沒有拷貝這個說法,他們被修改之后,引用地址就是直接改變了,如下面

但是,如果不可變類型內(nèi)部有嵌套的可變類型的時候,還是可以使用深復制的

另外要提醒一句,平時我們用的最多的直接賦值(或者可以說是直接傳遞引用)的方法,比如下面的例子

他是將a和b兩個可變元素同時指向一個內(nèi)存地址,所以,任何改變都是波及到a和b的

最后

可變類型:list , set , dict

不可變類型:int, str , float , tuple

淺復制方法:[:] , copy.copy() ,  使用工廠函數(shù)(list/dir/set)

深復制方法:copy.deepcopy()

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 將Python字符串生成PDF的實例代碼詳解

    將Python字符串生成PDF的實例代碼詳解

    這篇文章主要介紹了將Python字符串生成PDF的實例代碼,本文通過代碼給大家介紹的非常詳細,具有一定的參考借鑒價值 ,需要的朋友可以參考下
    2019-05-05
  • 使用Pycharm創(chuàng)建一個Django項目的超詳細圖文教程

    使用Pycharm創(chuàng)建一個Django項目的超詳細圖文教程

    Django是比較經(jīng)典的Python web框架,最近剛好在項目中用到了Django,所以下面這篇文章主要給大家介紹了關(guān)于使用Pycharm創(chuàng)建一個Django項目的超詳細圖文教程,文中介紹的非常詳細,需要的朋友可以參考下
    2022-08-08
  • VSCode下好用的Python插件及配置

    VSCode下好用的Python插件及配置

    這篇文章主要介紹了微軟官方的Python插件,已經(jīng)自帶很多功能,下面是插件功能描述,其中部分內(nèi)容我做了翻譯,需要的朋友可以參考下
    2018-04-04
  • Python中動態(tài)創(chuàng)建類實例的方法

    Python中動態(tài)創(chuàng)建類實例的方法

    在Java中我們可以通過反射來根據(jù)類名創(chuàng)建類實例,那么在Python我們怎么實現(xiàn)類似功能呢?其實在Python有一個builtin函數(shù)import,我們可以使用這個函數(shù)來在運行時動態(tài)加載一些模塊
    2017-03-03
  • 淺析Python中的縮進錯誤

    淺析Python中的縮進錯誤

    在編程中,我們經(jīng)常會遇到錯誤,縮進錯誤是 Python 中最常見的錯誤之一,它會使我們的代碼難以理解,并且難以調(diào)試,下面小編就來和大家簡單聊聊Python中的縮進錯誤吧
    2023-10-10
  • python中模塊的__all__屬性詳解

    python中模塊的__all__屬性詳解

    這篇文章主要介紹了python中模塊的__all__屬性詳解,具有一定參考價值,需要的朋友可以了解下。
    2017-10-10
  • Django使用django-simple-captcha做驗證碼的實現(xiàn)示例

    Django使用django-simple-captcha做驗證碼的實現(xiàn)示例

    這篇文章主要介紹了Django使用django-simple-captcha做驗證碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-01-01
  • 詳解使用python的logging模塊在stdout輸出的兩種方法

    詳解使用python的logging模塊在stdout輸出的兩種方法

    這篇文章主要介紹了詳解使用python的logging模塊在stdout輸出的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • python中的torch常用tensor處理函數(shù)示例詳解

    python中的torch常用tensor處理函數(shù)示例詳解

    這篇文章主要介紹了python中的torch常用tensor處理函數(shù),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • Python進階之如何快速將變量插入有序數(shù)組

    Python進階之如何快速將變量插入有序數(shù)組

    在我們學習python的過程中,學習序列是一門必修課。本文我們就來一起看一看Python是如何快速將變量插入有序數(shù)組的,感興趣的可以了解一下
    2023-04-04

最新評論