Python列表中存放字典遇到的問(wèn)題及處理
列表中存放字典遇到的問(wèn)題
使用列表、字典之間的相互嵌套可以很容易的實(shí)現(xiàn)json數(shù)據(jù)格式,但是昨天在往列表中裝入字典時(shí)遇到了問(wèn)題:

直接使用append方法將字典添加到列表中,如果需要更改字典中的數(shù)據(jù),那么列表中的內(nèi)容也會(huì)發(fā)生改變,這是因?yàn)閐ict在Python里是object,不屬于primitive type(即int、float、string、None、bool)。
這意味著你一般操控的是一個(gè)指向object(對(duì)象)的指針,而非object本身。
下面是改善方法:使用copy()

列表和字典的存儲(chǔ)方式
數(shù)組如何存儲(chǔ)?
數(shù)組底層的存儲(chǔ)結(jié)構(gòu)是順序存儲(chǔ)結(jié)構(gòu),這樣的結(jié)構(gòu)有這樣一些優(yōu)點(diǎn):邏輯上相鄰的節(jié)點(diǎn)在物理位置上也是相鄰的,可以節(jié)省空間,并且可以實(shí)現(xiàn)隨機(jī)存?。ㄒ卜Q直接訪問(wèn))。創(chuàng)建一個(gè)數(shù)組時(shí),會(huì)在內(nèi)存中開(kāi)辟一塊固定長(zhǎng)度的區(qū)域用于直接存儲(chǔ)元素,擴(kuò)容要考慮這塊區(qū)域的后面是否有存儲(chǔ)其他對(duì)象,所以數(shù)組在定義好之后就無(wú)法擴(kuò)容了。而且在查詢時(shí),是根據(jù)索引和元素存儲(chǔ)大小去計(jì)算地址偏移量的,如果元素類型不一致,所占內(nèi)存空間不相同,就不能實(shí)現(xiàn)隨機(jī)存儲(chǔ),所以數(shù)組不能同時(shí)存儲(chǔ)不同類型的數(shù)據(jù);
列表如何存儲(chǔ)?
列表本質(zhì)是動(dòng)態(tài)的數(shù)組,列表存儲(chǔ)的是每個(gè)元素在內(nèi)存中的地址(即引用),當(dāng)列表中空白占位低于1/3時(shí),會(huì)在內(nèi)存中開(kāi)辟一塊更大的空間,并將舊列表中存儲(chǔ)的地址復(fù)制到新列表中,舊列表則被銷毀,這樣就實(shí)現(xiàn)了擴(kuò)容。
因?yàn)榱斜泶鎯?chǔ)的是元素的引用這個(gè)特性,而引用所占的內(nèi)存空間是相同的,這樣便可以同時(shí)存放不同類型的數(shù)據(jù)了。
Python中的列表與數(shù)組的區(qū)別在于:
- 數(shù)組定義好之后就無(wú)法擴(kuò)容了,而列表在定義好之后可以擴(kuò)容;
- 數(shù)組只能同時(shí)存儲(chǔ)一種類型的數(shù)據(jù),而列表可以同時(shí)存儲(chǔ)不同類型的數(shù)據(jù)。
字典如何存儲(chǔ)?
Python中的字典底層是通過(guò)散列表(哈希表)來(lái)實(shí)現(xiàn)的, “哈希表是根據(jù)關(guān)鍵碼值(Key value)而直接進(jìn)行訪問(wèn)的數(shù)據(jù)結(jié)構(gòu)。也就是說(shuō),它通過(guò)把關(guān)鍵碼值映射到表中一個(gè)位置來(lái)訪問(wèn)記錄,以加快查找的速度。這個(gè)映射函數(shù)叫做散列函數(shù),存放記錄的數(shù)組叫做散列表。”
字典本質(zhì)也是一個(gè)數(shù)組,但其索引是鍵經(jīng)過(guò)散列函數(shù)處理后得到的散列值,散列函數(shù)的目的是使鍵均勻地分布在散列表中,并且可以在內(nèi)存中以O(shè)(1)的時(shí)間復(fù)雜度進(jìn)行尋址,從而實(shí)現(xiàn)快速查找和修改。散列表其實(shí)是一個(gè)稀疏數(shù)組(總是有空白元素的數(shù)組稱為稀疏數(shù)組),散列表里的單元通常叫作表元。在字典的散列表當(dāng)中,每個(gè)鍵值對(duì)都占用一個(gè)表元,每個(gè)表元都有兩個(gè)部分,一個(gè)是對(duì)鍵的引用,另一個(gè)是對(duì)值的引用。散列表中散列函數(shù)的設(shè)計(jì)困難在于將數(shù)據(jù)均勻分布在散列表中,從而盡量減少散列碰撞和沖突。
字典如何添加和查詢?
添加:Python 調(diào)用內(nèi)部的散列函數(shù),將鍵(Key)作為參數(shù)進(jìn)行轉(zhuǎn)換,得到一個(gè)唯一的地址(這也就解釋了為什么給相同的鍵賦值會(huì)直接覆蓋的原因,因?yàn)橄嗤逆I轉(zhuǎn)換后的地址是一樣的),然后將值(Value)存放到該地址中。

查詢:使用散列函數(shù)將key轉(zhuǎn)換為數(shù)組的下標(biāo),并定位到數(shù)組對(duì)應(yīng)位置獲取value。
字典為什么是無(wú)序的?
1.鍵值的哈希碰撞,hash(key1) == hash(key2)時(shí),向字典里連續(xù)添加的這個(gè)兩個(gè)鍵的順序是不可以控制的,也是無(wú)法做到連續(xù)的,后來(lái)的鍵會(huì)按算法調(diào)整到其它位置。
序是不可以控制的,也是無(wú)法做到連續(xù)的,后來(lái)的鍵會(huì)按算法調(diào)整到其它位置。
2.字典空間擴(kuò)容,當(dāng)鍵的數(shù)量超過(guò)字典默認(rèn)開(kāi)的空間時(shí),字典會(huì)做空間擴(kuò)容,擴(kuò)容后的鍵順和創(chuàng)建順序就會(huì)發(fā)生變化,不受人為控制。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
python的tkinter、socket庫(kù)開(kāi)發(fā)tcp的客戶端和服務(wù)端詳解
本文介紹了TCP通訊流程和開(kāi)發(fā)步驟,包括客戶端和服務(wù)端的實(shí)現(xiàn),客戶端使用Python的tkinter庫(kù)實(shí)現(xiàn)圖形化界面,服務(wù)端使用socket庫(kù)監(jiān)聽(tīng)連接并處理消息,文章還提供了客戶端和服務(wù)端的代碼示例2025-01-01
Python使用os.path和pathlib模塊進(jìn)行文件路徑操作的詳細(xì)教程
文件路徑操作是Python編程中的重要功能,它允許程序處理文件和目錄的路徑,這篇文章主要介紹了Python使用os.path和pathlib模塊進(jìn)行文件路徑操作的詳細(xì)步驟,有需要的小伙伴可以了解下2026-03-03
Python執(zhí)行速度慢的原因及全面優(yōu)化方案
Python 作為解釋型語(yǔ)言確實(shí)存在一些性能瓶頸,但通過(guò)深入理解其底層機(jī)制并采取合適的優(yōu)化策略,可以顯著提升執(zhí)行效率,以下是系統(tǒng)的原因分析和優(yōu)化方法,需要的朋友可以參考下2025-07-07
python爬蟲(chóng)框架scrapy實(shí)現(xiàn)模擬登錄操作示例
這篇文章主要介紹了python爬蟲(chóng)框架scrapy實(shí)現(xiàn)模擬登錄操作,結(jié)合實(shí)例形式分析了scrapy框架實(shí)現(xiàn)模擬登陸操作的步驟、相關(guān)實(shí)現(xiàn)技巧與注意事項(xiàng),需要的朋友可以參考下2018-08-08
PyQt中使用QProcess運(yùn)行一個(gè)進(jìn)程的示例代碼
這篇文章主要介紹了在PyQt中使用QProcess運(yùn)行一個(gè)進(jìn)程,本例中通過(guò)按下按鈕,啟動(dòng)了windows系統(tǒng)自帶的記事本程序,即notepad.exe, 因?yàn)樗趙indows的系統(tǒng)目錄下,該目錄已經(jīng)加在了系統(tǒng)的PATH環(huán)境變量中,所以不需要特別指定路徑,需要的朋友可以參考下2022-12-12
在Linux中通過(guò)Python腳本訪問(wèn)mdb數(shù)據(jù)庫(kù)的方法
這篇文章主要介紹了在Linux中通過(guò)Python腳本訪問(wèn)mdb數(shù)據(jù)庫(kù)的方法,本文示例基于debian系的Linux系統(tǒng),需要的朋友可以參考下2015-05-05

