python列表嵌套引發(fā)的問(wèn)題總結(jié)
1.嵌套列表
Python中有一種內(nèi)置的數(shù)據(jù)類(lèi)型叫列表(list),它是一種容器,可以用來(lái)承載其他的對(duì)象(準(zhǔn)確的說(shuō)是其他對(duì)象的引用),列表中的對(duì)象可以稱(chēng)為列表的元素,很明顯我們可以把列表作為列表中的元素,這就是所謂的嵌套列表。
嵌套列表可以模擬出現(xiàn)實(shí)中的表格、矩陣、2D游戲的地圖(如植物大戰(zhàn)僵尸的花園)、棋盤(pán)(如國(guó)際象棋、黑白棋)等。
2.識(shí)別坑點(diǎn)
在使用嵌套的列表時(shí)要小心,否則很可能遭遇非常尷尬的情況,下面是一個(gè)小例子:
def main(): names = ['關(guān)羽', '張飛', '趙云', '馬超', '黃忠'] subjs = ['語(yǔ)文', '數(shù)學(xué)', '英語(yǔ)'] scores = [[0] * 3] * 5 for row, name in enumerate(names): print('請(qǐng)輸入%s的成績(jī)' % name) for col, subj in enumerate(subjs): scores[row][col] = float(input(subj + ': ')) print(scores) if __name__ == '__main__': main()
我們希望錄入5個(gè)學(xué)生3門(mén)課程的成績(jī),于是定義了一個(gè)有5個(gè)元素的列表,而列表中的每個(gè)元素又是一個(gè)由3個(gè)元素構(gòu)成的列表,這樣一個(gè)列表的列表剛好跟一個(gè)表格是一致的,相當(dāng)于有5行3列。
接下來(lái)我們通過(guò)嵌套的for-in循環(huán)輸入每個(gè)學(xué)生3門(mén)課程的成績(jī)。程序執(zhí)行完成后我們發(fā)現(xiàn),每個(gè)學(xué)生3門(mén)課程的成績(jī)是一模一樣的(尷尬),而且就是最后錄入的那個(gè)學(xué)生的成績(jī)。
3.區(qū)分兩個(gè)概念
要想把這個(gè)坑填平,我們首先要區(qū)分對(duì)象和對(duì)象的引用這兩個(gè)概念,而要區(qū)分這兩個(gè)概念,還得先說(shuō)說(shuō)內(nèi)存中的棧和堆。
我們經(jīng)常會(huì)聽(tīng)人說(shuō)起“堆棧”這個(gè)詞,但實(shí)際上“堆”和“棧”是兩個(gè)不同的概念。眾所周知,一個(gè)程序運(yùn)行時(shí)需要占用一些內(nèi)存空間來(lái)存儲(chǔ)數(shù)據(jù)和代碼,那么這些內(nèi)存從邏輯上又可以做進(jìn)一步的劃分。
對(duì)底層語(yǔ)言(如C語(yǔ)言)有所了解的程序員大都知道,程序中可以使用的內(nèi)存從邏輯上可以為五個(gè)部分,按照地址從高到低依次是:棧(stack)、堆(heap)、數(shù)據(jù)段(data segment)、只讀數(shù)據(jù)段(static area)和代碼段(code segment)。
棧用來(lái)存儲(chǔ)局部、臨時(shí)變量,以及函數(shù)調(diào)用時(shí)保存現(xiàn)場(chǎng)和恢復(fù)現(xiàn)場(chǎng)需要用到的數(shù)據(jù),這部分內(nèi)存在代碼塊開(kāi)始執(zhí)行時(shí)自動(dòng)分配,代碼塊執(zhí)行結(jié)束時(shí)自動(dòng)釋放,通常由編譯器自動(dòng)管理。
堆的大小不固定,可以動(dòng)態(tài)的分配和回收,因此如果程序中有大量的數(shù)據(jù)需要處理,這些數(shù)據(jù)通常都放在堆上,如果堆空間沒(méi)有正確的被釋放會(huì)引發(fā)內(nèi)存泄露的問(wèn)題,而像Python、Java等編程語(yǔ)言都使用了垃圾回收機(jī)制來(lái)實(shí)現(xiàn)自動(dòng)化的內(nèi)存管理(自動(dòng)回收不再使用的堆空間)。
4.小例子
所以,下面的代碼中,變量a并不是真正的對(duì)象,它是對(duì)象的引用,相當(dāng)于記錄了對(duì)象在堆空間的地址,通過(guò)這個(gè)地址我們可以訪問(wèn)到對(duì)應(yīng)的對(duì)象。
a = object() b = ['apple', 'pitaya', 'grape']
同理,變量b是列表容器的引用,它引用了堆空間上的列表容器,而列表容器中并沒(méi)有保存真正的對(duì)象,它保存的也僅僅是對(duì)象的引用。
知道了這一點(diǎn),我們可以回過(guò)頭看看剛才的程序,我們對(duì)列表進(jìn)行[[0]* 3] * 5操作時(shí),僅僅是將[0, 0, 0] 這個(gè)列表的地址進(jìn)行了復(fù)制,并沒(méi)有創(chuàng)建新的列表對(duì)象。
所以,容器中雖然有5個(gè)元素,但是這5個(gè)元素引用了同一個(gè)列表對(duì)象。這一點(diǎn)可以通過(guò)id函數(shù)檢查scores[0]和scores[1]的地址得到證實(shí)。在此我們舉一個(gè)小例子,讀者朋友們可以敲一敲加深印象。
a = [[0]*3]*5id(a[0]) id(a[1]) # id相等
5.正確代碼
所以,正確的代碼應(yīng)該按照如下的方式進(jìn)行修改:
def main(): names = ['關(guān)羽', '張飛', '趙云', '馬超', '黃忠'] subjs = ['語(yǔ)文', '數(shù)學(xué)', '英語(yǔ)'] scores = [[]] * 5 for row, name in enumerate(names): print('請(qǐng)輸入%s的成績(jī)' % name) scores[row] = [0] * 3 #變?yōu)椴辉偾短? for col, subj in enumerate(subjs): scores[row][col] = float(input(subj + ': ')) print(scores) if __name__ == '__main__': main()
或者:
def main(): names = ['關(guān)羽', '張飛', '趙云', '馬超', '黃忠'] subjs = ['語(yǔ)文', '數(shù)學(xué)', '英語(yǔ)'] scores = [[0] * 3 for _ in range(5)] for row, name in enumerate(names): print('請(qǐng)輸入%s的成績(jī)' % name) scores[row] = [0] * 3 for col, subj in enumerate(subjs): scores[row][col] = float(input(subj + ': ')) print(scores) if __name__ == '__main__': main()
總結(jié)
本文介紹使用嵌套列表需要注意的問(wèn)題及解決措施,以此避免在使用嵌套列表或者復(fù)制對(duì)象時(shí)可能遇到的坑。
到此這篇關(guān)于python列表嵌套引發(fā)的問(wèn)題總結(jié)的文章就介紹到這了,更多相關(guān)python列表嵌套內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用機(jī)器學(xué)習(xí)預(yù)測(cè)房?jī)r(jià)
這篇文章主要介紹了利用機(jī)器學(xué)習(xí)回歸模型預(yù)測(cè)房?jī)r(jià),解釋清晰,代碼詳細(xì),是很不錯(cuò)的機(jī)器學(xué)習(xí)實(shí)戰(zhàn)演練,對(duì)機(jī)器學(xué)習(xí)感興趣的朋友可以參考一下2021-04-04Python的代理類(lèi)實(shí)現(xiàn),控制訪問(wèn)和修改屬性的權(quán)限你都了解嗎
這篇文章主要為大家詳細(xì)介紹了Python的代理類(lèi)實(shí)現(xiàn),控制訪問(wèn)和修改屬性的權(quán)限,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03Python 對(duì)象中的數(shù)據(jù)類(lèi)型
對(duì)于python,一切事物都是對(duì)象,程序中存儲(chǔ)的所有數(shù)據(jù)都是對(duì)象,對(duì)象基于類(lèi)創(chuàng)建。這篇文章主要介紹了Python 對(duì)象之?dāng)?shù)據(jù)類(lèi)型 ,需要的朋友可以參考下2017-05-05在Tensorflow中實(shí)現(xiàn)leakyRelu操作詳解(高效)
這篇文章主要介紹了在Tensorflow中實(shí)現(xiàn)leakyRelu操作詳解(高效),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06Sublime?Text4?配置?Python3?環(huán)境、代碼提示、編譯報(bào)錯(cuò)的解決方案
這篇文章主要介紹了Sublime?Text4?配置?Python3?環(huán)境、代碼提示、編譯報(bào)錯(cuò)教程,通過(guò)圖文并茂的形式給大家介紹了配置自動(dòng)代碼提示的方法,需要的朋友可以參考下2022-01-01Python使用Networkx實(shí)現(xiàn)復(fù)雜的人物關(guān)系圖
日常工作、生活中我們經(jīng)常會(huì)遇到一些復(fù)雜的事務(wù)關(guān)系,比如人物關(guān)系,那如何才能清楚直觀的看清楚這些任務(wù)關(guān)系呢?所以小編給大家介紹了Python如何使用Networkx實(shí)現(xiàn)復(fù)雜的人物關(guān)系圖,文中通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下2023-11-11python實(shí)現(xiàn)在cmd窗口顯示彩色文字
今天小編就為大家分享一篇python實(shí)現(xiàn)在cmd窗口顯示彩色文字,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-06-06解決python字典對(duì)值(值為列表)賦值出現(xiàn)重復(fù)的問(wèn)題
今天小編就為大家分享一篇解決python字典對(duì)值(值為列表)賦值出現(xiàn)重復(fù)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-01-01