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 MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...