Python 提高篇學習筆記(一):深拷貝和淺拷貝

文章目錄

  • 一、什么是對象的引用
  • 二、深拷貝和淺拷貝
    • 2.1 淺拷貝(Shallow Copy)
    • 2.2 深拷貝(Deep Copy)
    • 2.3 copy.copy和copy.deepcopy的區別

一、什么是對象的引用

在 Python 中,對象的引用是指變量指向內存中某個對象的地址或標識符。當你創建一個新的對象(比如一個整數、字符串、列表等),Python 會分配一塊內存來存儲這個對象,并且給這個對象分配一個唯一的標識符(也就是對象的地址)。當你將這個對象賦值給一個變量時,實際上這個變量就存儲了對該對象的引用,而不是對象本身。這意味著變量并不直接包含對象的值,而是指向存儲這個值的內存地址。

舉例:

In [19]: x = [1, 2, 3] # 創建一個列表對象,并將其引用賦給變量x
In [20]: y = x # y和x現在指向同一個列表對象
In [21]: # 修改x所指向的列表對象
In [22]: x.append(4)
In [23]: print(y) # 輸出[1, 2, 3, 4],因為y引用的是和x相同的列表對象
[1, 2, 3, 4]

在這個例子中,[1, 2, 3] 是一個列表對象,在內存中有自己的地址。x 這個變量包含了對這個列表對象的引用,而不是列表對象本身。如果你創建一個新的變量 y = x,那么 y 實際上也會指向同一個列表對象,即它們共享相同的引用。圖示:
在這里插入圖片描述
因此,對于可變對象(如列表、字典等), 如果多個變量引用了同一個對象,當你通過一個變量修改這個對象時,其他引用了相同對象的變量也會反映出這個修改。這是因為它們引用的是同一個對象,而不是對象的副本。對于不可變對象(如整數、字符串等), 由于對象本身是不可變的,任何修改都會導致新對象的創建,而不會影響原始對象,因為對不可變對象的修改實際上是創建了一個新對象并將變量重新指向新對象的地址。舉例:

In [33]: x = 300
In [34]: y = x
In [35]: y = 400
In [36]: print(x, y)
300 400

圖示:
在這里插入圖片描述
補充:在 Python 中,== 和 is 是用于比較對象的運算符,但它們的作用不同:

== 操作符用于比較兩個對象的值是否相等。
is 操作符用于檢查兩個對象是否是同一個對象,也就是比較它們的身份標識(即內存地址/引用)是否相同。示例如下:

In [39]: a = [1, 2, 3]
In [40]: b = [1, 2, 3]
In [41]: # 比較值是否相等
In [42]: print(a == b) # 輸出True,因為列表a和列表b中的元素都相同
True
In [43]: # 檢查是否是同一個對象
In [44]: print(a is b) # 輸出False,因為a和b是不同的對象,即在內存地址/引用不一樣
False

注意: 在 Python 中,有一個特定的機制用于緩存一定范圍內的小整數對象,這個范圍通常是 -5~256 (這個范圍可能會因 Python 版本和具體實現而略有不同)。 這意味著在這個范圍內的整數對象在 Python 程序中的生命周期中會被緩存并重用,而不是每次都創建新的對象。這個緩存機制是為了提高性能和節省內存。因為這些小整數在許多情況下是常用的,Python 會在啟動時預先創建這些對象并將其緩存起來,當你需要使用這些整數時,Python 會直接返回緩存中的對象而不是創建新的對象。這種緩存機制使得在相同范圍內的整數對象比較時,使用 is 操作符可能返回 True,因為它們指向相同的對象:

In [45]: x = 10
In [46]: y = 10
In [47]: print(x is y) # 輸出True,因為x和y是同一個對象,由于小整數的緩存機制(有些也稱為常量池)
True
In [48]: a = 300
In [49]: b = 300
In [50]: print(a is b) # 輸出False,因為超出了小整數的緩存范圍,a和b是不同的對象
False

二、深拷貝和淺拷貝

在 Python 中,深拷貝和淺拷貝是用于創建對象副本的概念。在理解這兩者之間的區別之前,讓我們先來看看它們的定義和用法。

2.1 淺拷貝(Shallow Copy)

淺拷貝創建一個新對象,但是只復制了對象的引用。這意味著原始對象及其副本引用了相同的子對象。當你對原始對象或副本對象做出改變時,子對象的改變會反映在兩者之間。

在 Python 中,可以使用 copy 模塊中的 copy() 方法來進行淺拷貝:

In [65]: import copy
In [66]: original_list = [1, 2, [3, 4]]
In [67]: new_list = original_list  # 賦值是最簡單的淺拷貝
In [68]: id(original_list) # 用來顯示original_list指向的數據的內存地址
Out[68]: 1837971633856
In [69]: id(new_list) # 用來顯示new_list指向的數據的內存地址
Out[69]: 1837971633856In [70]: shallow_copied_list = copy.copy(original_list)
In [71]: # 修改shallow_copied_list副本中的元素
In [72]: shallow_copied_list[0] = 5
In [73]: # 修改子對象(原始對象和副本對象共享的對象)
In [74]: shallow_copied_list[2][0] = 6
In [77]: print(original_list, new_list)
[1, 2, [6, 4]] [1, 2, [6, 4]]
In [78]: print(shallow_copied_list)
[5, 2, [6, 4]]

圖示:
在這里插入圖片描述
字典示例:

In [131]: import copy
In [132]: d = dict(name='AmoXiang',age=19,hobby_list=['dance', 'sing'])
In [133]: co = copy.copy(d)
In [134]: d
Out[134]: {'name': 'AmoXiang', 'age': 19, 'hobby_list': ['dance', 'sing']}
In [135]: co
Out[135]: {'name': 'AmoXiang', 'age': 19, 'hobby_list': ['dance', 'sing']}
In [136]: id(d),id(co)
Out[136]: (1838005229056, 1838001691136)
In [137]: d['name'] = 'Amo'
In [138]: d
Out[138]: {'name': 'Amo', 'age': 19, 'hobby_list': ['dance', 'sing']}
In [139]: co
Out[139]: {'name': 'AmoXiang', 'age': 19, 'hobby_list': ['dance', 'sing']}
In [140]: co['hobby_list'].append('swim')
In [141]: co
Out[141]: {'name': 'AmoXiang', 'age': 19, 'hobby_list': ['dance', 'sing', 'swim']}
In [142]: d
Out[142]: {'name': 'Amo', 'age': 19, 'hobby_list': ['dance', 'sing', 'swim']}
In [143]: id(d['name']),id(co['name'])
Out[143]: (1837976233200, 1837949658800)
In [144]: id(d['age']),id(co['age'])
Out[144]: (1837896002416, 1837896002416)
In [145]: id(d['hobby_list']),id(co['hobby_list'])
Out[145]: (1837979180480, 1837979180480)
In [146]: co['age'] = 20
In [147]: co
Out[147]: {'name': 'AmoXiang', 'age': 20, 'hobby_list': ['dance', 'sing', 'swim']}
In [148]: d
Out[148]: {'name': 'Amo', 'age': 19, 'hobby_list': ['dance', 'sing', 'swim']}

淺拷貝對不可變類型和可變類型的 copy 不同:
copy.copy 對于可變類型,會進行淺拷貝
copy.copy 對于不可變類型,不會拷貝,僅僅是指向

In [159]: import copy
In [160]: a = [1,2,3]
In [161]: b = copy.copy(a)
In [162]: id(a),id(b)
Out[162]: (1838001649984, 1837979060672)
In [163]: a.append(4)
In [164]: a
Out[164]: [1, 2, 3, 4]
In [165]: b
Out[165]: [1, 2, 3]
In [166]: a = (1,2,3)
In [167]: b = copy.copy(a)
In [168]: id(a),id(b)
Out[168]: (1838005603584, 1838005603584)

2.2 深拷貝(Deep Copy)

深拷貝創建一個全新的對象,同時遞歸地復制了所有子對象。這意味著原始對象及其副本不共享任何子對象。無論你對原始對象還是副本對象做出任何改變,都不會影響對方。同樣使用 copy 模塊中的 deepcopy() 方法進行深拷貝:

In [90]: import copy
In [91]: original_list = [1, 2, [3, 4]]
In [92]: deep_copied_list = copy.deepcopy(original_list)
In [93]: id(original_list)
Out[93]: 1838005694912
In [94]: id(deep_copied_list)
Out[94]: 1838005773312
In [95]: # 修改副本的元素
In [96]: deep_copied_list[0] = 5
In [97]: # 修改子對象(原始對象和副本對象共享的對象)
In [98]: deep_copied_list[2][0] = 6
In [99]: print(original_list)  # 輸出:[1, 2, [3, 4]]
[1, 2, [3, 4]]
In [100]: print(deep_copied_list)  # 輸出:[5, 2, [6, 4]]
[5, 2, [6, 4]]
In [101]: print(id(original_list[2]))
1838004780096
In [102]: print(id(deep_copied_list[2]))
1838001793984

圖示:
在這里插入圖片描述

2.3 copy.copy和copy.deepcopy的區別

copy.copy 圖示:
在這里插入圖片描述
copy.deepcopy 有興趣的可以自己畫一下,這里我就不再進行贅述(圖太難畫了,偷下懶)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/160492.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/160492.shtml
英文地址,請注明出處:http://en.pswp.cn/news/160492.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[技術雜談]計算機系統硬件類名稱

在各種編程語言都可以見到利用WMI查詢計算機硬件信息,因此知道有哪些計算機硬件名稱非常有必要,下面列舉了所有計算機硬件名稱可以查詢。 本文內容 冷卻設備類輸入設備類大容量存儲類主板、控制器和端口類 顯示另外 6 個 計算機系統硬件類別將表示硬…

git修改遠程分支名稱

先拉取old_branch最新代碼到本地 git checkout old_branchgit pull origin old_branch本地修改后并推送 git branch -m old_branch new_branch # 修改分支名稱git push --delete origin old_branch # 刪除在遠程的老分支推送新分支 git push origin new_branch本地分支與遠…

除自身以外數組的乘積[中等]

優質博文:IT-BLOG-CN 一、題目 給你一個整數數組nums,返回數組answer,其中answer[i]等于nums中除nums[i]之外其余各元素的乘積。題目數據保證數組nums之中任意元素的全部前綴元素和后綴的乘積都在32位整數范圍內。請不要使用除法&#xff0…

【Qt開發流程】之富文本處理

描述 Scribe框架提供了一組類,用于讀取和操作結構化的富文本文檔。與Qt中以前的富文本支持不同,新的類集中在QTextDocument類上,而不是原始文本信息。這使開發者能夠創建和修改結構化的富文本文檔,而不必準備中間標記格式的內容。…

【數據結構】A : A DS圖_傳遞信息

A : A DS圖_傳遞信息 Description 小明在和他的小伙伴們玩傳消息游戲,游戲規則如下: 有n名玩家,所有玩家編號分別為0~n-1,其中小明編號為0;每個玩家都有固定的若干個可傳信息的其他玩家(也可能沒有)。傳消息的關系是…

busybox制作根文件系統2

上篇內容使用busybox制作好了根文件系統,接下來需要進行一些測試和功能的完善! 根文件系統的測試 測試根文件系統的時候不是直接燒寫到EMMC里面,這樣測試效率太低了,Ubuntu的rootfs目錄已經保存了根文件系統,只需要在…

向量數據庫,展望AGI時代

無論是向量數據庫,還是大模型,歸根結底,大家在追捧它時的心態,焦慮大于需求。 向量數據庫的熱潮,在一定程度上“外化”了人們的焦慮。 但這并不能否定向量數據庫的實際價值,甚至更長遠來看,向…

【C++】linux下的gdb程序調試

目錄 【C】Linux 下的 GDB 程序調試1. 安裝 GDB2. 編譯程序3. 啟動 GDB4. 設置斷點5. 執行程序6. 調試命令7. 調試崩潰8. 結束調試 【C】Linux 下的 GDB 程序調試 在開發 C 程序時,出現 bug 是常見的。調試是找出程序錯誤的關鍵步驟之一。在 Linux 環境下&#xff…

RedisTemplate使用詳解

RedisTemplate介紹StringRedisTemplate介紹RedisConnectionFactory介紹RedisConnectionFactory源碼解析 RedisOperations介紹RedisOperations源碼解析 RedisTemplate使用連接池配置RedisTemplate連接池連接池配置 RedisTemplate應用場景RedisTemplate主要特點RedisTemplate使用…

redis運維(十六) 有序集合

一 有序集合 把握一點: 各種redis 命令都提供各種語言對應的API 接口,后續API是關鍵 ① 概念 1、sorted set --> 有序集合2、redis有序集合也是集合類型的一部分,所以它保留了集合中元素不能重復的特性3、但是不同的是,有序集合給每個元素多設置…

什么是數字孿生?

數字孿生是指通過數字化技術手段,將現實世界中的實體物理系統或過程與其數字化模型相連接,實現實體物理系統或過程的虛擬仿真、監測、預測和優化等功能的一種技術。數字孿生技術可以將物理系統的運行狀態、性能參數、故障信息等實時反饋到數字模型中&…

轉型做視頻了,博客就是稿子,繼續堅持寫博客,同時發布視頻,能寫博客說明思路清晰了,能再講明白,理解就更透徹了,緊跟上時代發展。

1,今天特別記錄下,B站給開通了《合集》功能 最近使用視頻制作了幾個視頻。播放量還不錯,最好的已經到了 2.6K了。 然后粉絲也漲到了 200個。 添加鏈接描述 緊跟時代:從寫博客到錄視頻,粉絲大漲,突破200個&…

vue開發一、在Vue中引入ElementUI二、在Vue中使用阿里圖標庫

目錄 一、在Vue中引入ElementUI1. 安裝ElementUI2. 引入ElementUI3. 使用ElementUI組件 二、在Vue中使用阿里圖標庫1. 在阿里圖標庫中選擇圖標2. 下載圖標3. 引入圖標4. 使用圖標 總結 一、在Vue中引入ElementUI ElementUI是一種基于Vue的第三方UI庫,提供了許多常用…

接口自動化測試 —— 工具、請求與響應

一、工具: 1.工具介紹 postman :很主流的API測試工具,也是工作里面使用最廣泛的研發工具。 JMeter: ApiPost: 2.安裝postman: 安裝好直接打開,不用注冊。 二、通信模式: 1、…

【Java 進階篇】從Java對象到JSON:Jackson的魔法之旅

在現代的軟件開發中,處理數據的能力是至關重要的。而當我們談及數據格式時,JSON(JavaScript Object Notation)通常是首選。為了在Java中輕松地將對象轉換為JSON,我們需要一種強大而靈活的工具。這時,Jackso…

【Java 進階篇】Redis:打開緩存之門

介紹 Redis(Remote Dictionary Server)是一個高性能的鍵值對存儲系統,被廣泛用作緩存、消息中間件和數據庫。它以其快速的讀寫能力、支持多種數據結構和豐富的功能而聞名。在這篇博客中,我們將深入了解Redis的概念、安裝以及基本…

MQTT協議消息代理服務遠程連接

目錄 1. Linux 搭建 Mosquitto 2. Linux 安裝Cpolar 3. 創建MQTT服務公網連接地址 4. 客戶端遠程連接MQTT服務 5. 代碼調用MQTT服務 6. 固定連接TCP公網地址 7. 固定地址連接測試 Mosquitto是一個開源的消息代理,它實現了MQTT協議版本3.1和3.1.1。它可以在不…

第二十章:多線程

進程 線程的特點 1.進程是資源分配的最小單位&#xff0c;線程是最小的執行單位 2.一個進程可以有多個線程 3.線程共享進程資源 package twentyth; public class ThreadTest extends Thread { public void run() { for (int i 1; i < 10; i) {//繼承重…

Unity開發之C#基礎-File文件讀取

前言 今天我們將要講解到c#中 對于文件的讀寫是怎樣的 那么沒接觸過特別系統編程小伙伴們應該會有一個疑問 這跟文件有什么關系呢&#xff1f; 我們這樣來理解 首先 大家對電腦或多或少都應該有不少的了解吧 那么我們這些軟件 都是通過變成一個一個文件保存在電腦中 我們才可以…

【2023C卷最新題目】20天拿下華為OD筆試之【貪心】2023C-找座位/2023B-座位調整-全網注釋最詳細分類最全的華為OD真題題解

文章目錄 題目描述與示例題目描述輸入輸出說明示例一輸入輸出 示例二輸入輸出說明 解題思路代碼PythonJavaC時空復雜度 相同問題不同描述2023C-找座位題目描述輸入描述輸出描述示例一輸入輸出 示例二輸入輸出 華為OD算法/大廠面試高頻題算法練習沖刺訓練 題目描述與示例 題目描…