Python基礎-17對象引用和拷貝

来源:https://www.cnblogs.com/surpassme/archive/2020/06/01/13028213.html
-Advertisement-
Play Games

17.對象引用和拷貝 我們先來看看以下向個概念 變數:是系統變數名錶中的元素,通常是由程式員進行定義聲明 對象:是電腦分配的一塊記憶體,需要足夠的空間去表示它的值 引用:是自動形成的從變數到對象的指針 可變對象:允許對自身內容進行修改。如list、dict、set、自定義類型等。 不可變對象:不允許 ...


17.對象引用和拷貝

    我們先來看看以下向個概念

  • 變數:是系統變數名錶中的元素,通常是由程式員進行定義聲明
  • 對象:是電腦分配的一塊記憶體,需要足夠的空間去表示它的值
  • 引用:是自動形成的從變數到對象的指針
  • 可變對象:允許對自身內容進行修改。如list、dict、set、自定義類型等。
  • 不可變對象:不允許對自身內容進行修改。如果對一個不可變對象進行賦值,實際上是生成一個新的對象,再讓變數指向這個對象。如int、float、bool、str、tuple

如果有瞭解Java的堆棧知識(堆存儲真實的數據,而棧則是存儲相應引用地址),則這裡所指的對象可以理解為堆,而引用則代表棧。

17.1 對象引用

    對象的賦值實際上就是對象引用,創建一個對象並將其賦值給一個變數時,該變數實際是指向了該對象的引用,可使用內置函數id()查看返回值。變數名與對象之間的示意圖如下所示:

170101對象與變數名關係.png

示例如下所示:

>>> tempA=[1,3,5]
>>> tempB=tempA    # tempB對tempA的引用
>>> tempB
[1, 3, 5]
>>> tempB[0]=-100  # 修改tempB的元素,tempA相應的元素也同步進行了更改
>>> tempA
[-100, 3, 5]
>>> tempB
[-100, 3, 5]
>>> id(tempA),id(tempB)
(2614814009544, 2614814009544)
>>> tempB is tempA
True

    在上面的例子中,本意是想修改tempB中第一個元素,而連帶temA也被一起修改了。因為tempA和tempB引用的是同一個對象,修改其中任意一個變數都會影響到另一個。為了避免這種情況,必須創建對象的副本而不是創建新引用。對於像列表和字典這種容器類對象,可以使用兩種拷貝操作:淺拷貝深拷貝

17.2 對象的拷貝

17.2.1 淺拷貝

    淺拷貝將創建一個新對象,其內容是原對象中元素的引用。可以使用模塊copy中的copy()函數,另外也可使用切片操作、對象的copy方法。其特點如下所示:

  • 兩個變數的記憶體地址不同
  • 變數之間存在共用值的情況
  • 對其中一個變數進行更改後,另外的變數也會隨之改變

如果使用等號賦值時,連對象都不會重新創建。只有重新創建對象併為其賦值,才會發生淺拷貝

    示例代碼如下所示:

>>> a=[1,2,[3,4]]
>>> b=list(a)          # 創建a的一個淺複製
>>> b is a
False
>>> b.append(100)      # 給b追加一個元素
>>> b
[1, 2, [3, 4], 100]    # 修改b中的一個元素
>>> a
[1, 2, [3, 4]]
>>> b[2][0]=-98
>>> b
[1, 2, [-98, 4], 100]
>>> a                  # a中與b共有的元素值也會發生改變
[1, 2, [-98, 4]]
>>> id(a),id(b)
(2614813897288, 2614813796232)

>>> aa=[1,2,[3,4]]
>>> bb=aa              # 直接賦值並沒有發生淺拷貝
>>> id(aa),id(bb)
(1960262980168, 1960262980168)
>>> aa = list(bb)
>>> id(aa),id(bb)
(1960263019208, 1960262980168) # 發生了淺拷貝,因此兩者的id也不一樣
>>> id(aa[0]),id(aa[1]),id(aa[2])
(140715523797264, 140715523797296, 1960263020232)
>>> id(bb[0]),id(bb[1]),id(bb[2])
(140715523797264, 140715523797296, 1960263020232) # 雖然發生了淺拷貝,但內部元素卻都指向相同的對象

    在上述示例中,a和b是單獨的列表對象,但它們包含的元素是共用的。因此修改b的一個元素也會修改a中的對應元素。而在aa和bb中,在發生淺拷貝後,aa和bb兩個對象的地址不一樣,而其內部元素卻指向了相同的對象。

17.2.2 深拷貝

    深拷貝將創建一個新對象並對其賦值時,原對象中的所有元素都會在新對象中重新創建一次。常用模塊copy中的deepcopy()函數,其特點如下所示:

  • 變數間的記憶體地址不同
  • 變數間有各自的值,且互不影響
  • 對其任意一個變數的值進行修改,不會影響另外一個

    示例代碼如下所示:

>>> import copy
>>> a=[1,2,[3,4]]
>>> b=copy.deepcopy(a) # 深拷貝
>>> b is a
False
>>> b.append(100)
>>> b
[1, 2, [3, 4], 100]
>>> a
[1, 2, [3, 4]]
>>> b[2][0]=-98
>>> b
[1, 2, [-98, 4], 100]
>>> a            # 在修改b之後,對a沒有任何影響
[1, 2, [3, 4]]
>>> id(a),id(b)
(1960263017096, 1960263112136)

>>> aa=[1,2,[3,4]]
>>> bb=copy.deepcopy(aa) # 深拷貝
>>> id(aa),id(bb)
(2540655565384, 2540656480520) # 地址發生改變
>>> id(aa[0]),id(aa[1]),id(aa[2])
(140715523797264, 140715523797296, 2540655563912)
>>> id(bb[0]),id(bb[1]),id(bb[2])
(140715523797264, 140715523797296, 2540656401224)

    在列印內部地址發現,前兩個元素地址沒有屬性改變,是因為在Python數字和字元串屬於不可變對象。為提升效率,Python語言中,在記憶體中只存在一份不可變對象,並將其地址(即引用)賦值給其他變數。

淺拷貝和深拷貝僅僅是針對可變對象的,對於不可變對象,賦值的操作過程都是直接將引用賦值。

17.3 小結

    現在假設有一個對象a=[ 1, 2 ,[ 3,4 ] ],有另外一個對象,分別進行=賦值、淺拷貝和深拷貝,其使用小結如下所示:

  • 1.使用=直接賦值,不會發生淺拷貝和深拷貝情況,僅相當於增加一個新標簽,並不產生新的對象,示意圖如下所示:

170301等號賦值.png

    針對這種情況,有時候也被比喻為舊瓶裝舊酒

  • 2.使用淺拷貝之後,會創建一個新的對象,但內部元素仍然保持一致,示意圖如下所示:

170302淺拷貝.png

    因為元素中1和2為不可變對象,它們互不影響,給人的感覺就相當於複製了一份。這種就是淺拷貝,有時候也被比喻為新瓶裝舊酒,雖然產生了新的對象,但裡面的內容還是來自同一份。

  • 3.使用深拷貝之後,會創建一個新的對象,原對象中的所有元素會被重新創建一次,示意圖如下所示:

170303深拷貝.png

    對象a和b前兩個元素因是不可變對象,所會在進行深拷貝之後,地址不會進行更改。而第三個元素為可變對象,則相當創建了一個副本。所以深拷貝也可以理解為,不僅是對象自身的拷貝,對於對象中每一個子元素,也都進行同樣的拷貝。針對這種情況,有時候也被比喻為新瓶裝新酒

  • 4.淺拷貝和深拷貝針對的是可變對象

參考網址:https://segmentfault.com/a/1190000017001073

本文地址:https://www.cnblogs.com/surpassme/p/13028213.html
本文同步在微信訂閱號上發佈,如各位小伙伴們喜歡我的文章,也可以關註我的微信訂閱號:woaitest,或掃描下麵的二維碼添加關註:
MyQRCode.jpg


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 概述 Express是目前最流行的基於Node.js的Web開發框架,可以快速地搭建一個完整功能的網站。 Express上手非常簡單,首先新建一個項目目錄,假定叫做hello-world。 $ mkdir hello-world 進入該目錄,新建一個package.json文件,內容如下。 { "n ...
  • 觀察者模式是一種經常使用的設計模式,在軟體系統中對象並不是孤立存在的,一個對象行為的改變可能會導致其他與之存在依賴關係的對象行為發生改變,觀察者模式用於描述對象之間的依賴關係。 模式動機 很多情況下,對象不是孤立存在的,想象這麼一個場景:你和女朋友去旅行,晚上回到賓館,女朋友穿著厚厚的大衣,從外表看 ...
  • Java生鮮電商平臺-生鮮電商數據分析思維以及指標(小程式/APP) 說明:在生鮮電商行業火爆和轉型的背後,數據分析往往成了主要的助推劑之一,通過對商品、用戶、平臺數據的分析,商家就能知道什麼樣的商品好賣,什麼樣的人愛買,哪一類的促銷活動更受歡迎等等,從而對症下藥調整策略,精準營銷。於是,近年來電商 ...
  • 1、數據類型 go語言支持的基礎類型: 整型:int,int8,int16,int32,int64 無符號整型:uint,uint8,uint16,uint32,uint64 其中預設類型為int,int表示32位或64位與操作系統有關 位元組:byte 布爾:bool 浮點型:float32,flo ...
  • Java中內置類及其方法的使用通常翻閱對應的API文檔即可,但是對於常用的一些類和方法還是需要我們能夠熟練的使用。 一、System System.gc():手動啟動垃圾回收器,垃圾回收器通常是自動啟動的,某些時候Java可能覺得當下的情況並不需要啟動gc,但是你又想啟動的話,就可以調用這個方法手動 ...
  • python2 預設的編碼方式是ASCII碼 在文件的首行:#-- encoding:utf-8 -- python3 預設編碼方式utf-8 0、列印內容 print () print('Hellow World !') 1、變數 變數:就是將一些運算的中間結果暫存到記憶體中,以便後續代碼調用。 必 ...
  • *6.38(生成隨機字元)使用程式清單6-10RandomCharacter中的方法,列印100個大寫字母及100個一位數字,每行列印10個。 *6.38(Generate random characters) Use the methods in RandomCharacter in Listin ...
  • pydbclib是一個通用的python關係型資料庫操作工具包,使用統一的介面操作各種關係型資料庫(如 oracle、mysql、postgres、hive、impala等)進行增刪改查,它是對各個python資料庫連接驅動包(如sqlalchemy、pymysql、cx_Oracle、pyhive ...
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...