- 你也能看得懂的Python算法書
- 王碩 董文馨 張舒行 張潔編著
- 6467字
- 2019-07-25 11:36:20
1.3 列表
列表是Python中五種標準變量類型的一種。一系列按順序排列的元素組成了列表,一個列表中可以包含字符、數字、字符串,甚至子列表。
在Python中,同一個列表中可以包含多個不同類型的元素,也就是說,不同類型的變量可以存在于同一個列表內,如圖1.13所示。列表的長度以及列表內元素的值都是動態的—它們可以隨時被修改。

圖1.13 包含列表的列表(list4)
1.3.1 定義列表
在Python中,列表用中括號表示([])。
下面的程序中定義了4個不同的列表:
01 list1=[]
02 list2=[2,3,5,7]
03 list3=["a","b","c"]
04 list4=[1,4,2,"a",[2,3,5]]
很明顯,list1是一個空列表,它的內部不包含任何元素。通常在需要提前聲明變量類型為列表的情況下,用定義空列表來實現。第2行的list2是一個整數列表,它的每一個元素都是一個整型變量,而list3中的每一個元素都是一個字符串。最后,list4是一個包含多種元素的列表,可以看到,它內部有數字、字符串和列表這三種元素。
1.3.2 對元素進行操作
現在已有一個包含多種元素的列表:
01 mylist=[2,3,5,7,11,13,17,19,"integer","string","list",[123,456]]
列表內包含多種元素,那么如何調用這些列表內的元素進行計算和拼接等工作呢?
由于列表是一個有序集合,所以可以根據索引來找到每一個元素。元素的格式是列表的名稱+[索引],索引從0開始。比如,列表mylist的第一個元素就是mylist[0]。因為第一個元素的索引為0,所以最后一個元素的索引應該是列表的長度減1,如圖1.14所示。

圖1.14 列表mylist
如果列表中的元素還是一個列表,那么如何調用子列表內的元素呢?很簡單。比如在列表mylist中,最后一個元素是mylist[11],這個元素是一個列表。那么,這個子列表的第一個元素就是mylist[11][0]。
下面是對列表mylist內的元素進行的一些操作,并對結果進行輸出:
01 mylist=[2,3,5,7,11,13,17,19,"integer","string","list",[123,456]]
02 print(mylist[11][0]/mylist[1])
03 print(mylist[8]+" "+mylist[9])
運行程序,輸出結果為:
41.0
integer string
其中,mylist[11][0]是指 mylist 中第12個元素(子列表)的第1個元素,也就是123;mylist[1]是指mylist的第2個元素,也就是3。它們相除的商就是41.0。同理,mylist[8]和mylist[9]是指列表中的第9個元素和第10個元素,它們和一個空格拼接起來,就成了輸出結果的第2行“integer string”。
也可以修改列表中元素的值:
01 mylist=[2,3,5,7,11]
02 mylist[4]=9
03 print(mylist,mylist[4])
運行程序,輸出結果為:
[2,3,5,7,9]9
列表內的元素和變量一樣,值可以被隨時更新,也可以被用來賦值給其他變量。
列表中的元素個數是非固定、可以改變的。也就是說,可以往列表中添加新的元素,也可以把元素從列表中移除。先來看看如何往列表中添加元素。
給定一個元素為“2,3,5,7,13,17,19”的列表mylist,這個列表內的所有元素都是質數。要想把這個列表轉換為從2到23的有序質數列表,就要用到append和insert這兩個內置列表函數。
如圖1.15和圖1.16所示,內置函數append的功能是在列表的末尾插入新的元素,而函數insert的功能是在指定索引的位置插入新的元素,原本在這個索引位置處的元素及其后面的所有元素往后順移一位。

圖1.15 append函數

圖1.16 insert函數
在下面的程序中,每往列表中添加一個元素,就把整個列表打印出來,方便觀察規律:
01 mylist=[2,3,5,7,13,17,19]
02 mylist.append(23)
03 print(mylist)
04 mylist.insert(4,11)
05 print(mylist)
運行程序,輸出結果為:
[2,3,5,7,13,17,19,23]
[2,3,5,7,11,13,17,19,23]
可以看到,在append函數執行完畢后,列表的長度增加了一位,23被加在了列表的最后。而insert函數執行完后,新元素11被插到索引為4的位置,也就是mylist[4]的位置—第5個元素。原本排在第5個的元素13并沒有消失,它和它后方的元素全部往后移動了一位,也就是索引增加了1。由這個例子也可以看出,列表內置函數的調用方法是:列表名+句點+函數名+小括號,括號內是函數執行所需要的數據。
append函數的括號中填寫需要插入在列表末尾的元素,insert函數括號中的第一個數據填寫要插入的索引值,第二個數填寫需要插入的元素,中間用逗號隔開。這些語法都是固定的,只有按照正確的方法編寫程序才能按照設想運行。
再來看看如何從列表中移除元素。
如果要移除列表中的元素,有兩個函數可以選擇:remove和pop。remove函數的標準格式為:list.remove(obj),它的功能是移除指定列表(list)中某個值(obj)的第一個匹配項。pop函數的標準格式為:list.pop(index),它的功能是移除指定列表(list)中某個索引位置(index)上的元素,同時也返回被移除的元素的值。這兩種函數運行完畢—指定元素被移除后,它后方的所有元素向前移動一位,也就是索引減少1,如圖1.17所示。

圖1.17 移除元素
下面是一個具體的例子:
01 mylist=[2,3,4,5,6,2]
02 mylist.remove(2)
03 print(mylist)
04 num=mylist.pop(0)
05 print(mylist,num)
運行程序,輸出結果為:
[3,4,5,6,2]
[4,5,6,2]3
在這段程序中,remove函數移除了列表mylist中匹配到的第一個等于2的元素。由于列表的遍歷順序是按索引大小從小到大進行的,被移除的是第一個2,而不是最后的2。第4行中的pop函數移除了當前列表索引為0的數,也就是第一個數3,同時把3返回。
編寫程序時我選擇用變量num“接住”傳輸回來的元素,并將它和pop操作后的列表一起輸出,這就叫彈出元素。彈出功能可以在我們需要一次性使用列表中的數時使用(用完一次就丟掉)。
也可以選擇不用變量保存pop的返回值,而把它單純地作為一個用于移除元素的函數使用。如果pop的括號內沒有填寫要彈出的元素的索引(空括號),則默認彈出列表的最后一個元素。
要移除列表中的元素還有一個方法:
01 numbers=[1,2,3,4,5,6]
02 del numbers[2]
03 print(numbers)
運行程序,輸出結果為:
[1,2,4,5,6]
del函數的使用格式為“del+空格+要刪除的元素”,它和pop函數的刪除方法相似,需要提供列表名和索引,但它沒有pop函數返回被刪除的元素值的功能。
1.3.3 列表的順序
我們常常需要把字符串或者數字按首字母順序和數字大小排序。如何把大小隨機的元素按順序排列呢?如圖1.18所示。

圖1.18 排序
只需要一步:
01 mylist=[2,3,5,29,13,17,19]
02 mylist.sort()
03 print(mylist)
運行程序,輸出結果為:
[2,3,5,13,17,19,29]
經過列表內置函數 sort 的操作后,mylist 被進行了永久性的從小到大的排序—原來的順序無法復原了。如果列表里的元素都是字符串,則Python會自動按首字母從a到z的順序排列。需要注意的是,如果用sort函數進行排序,那么列表內的元素必須都是同一種類型,否則程序會出錯。
那么,如果想要從大到小排序呢?
01 mylist=[2,3,5,29,13,17,19]
02 mylist.sort()
03 mylist.reverse()
04 print(mylist)
運行上面的程序,輸出結果為:
[29,19,17,13,5,3,2]
在這段程序中,首先用sort函數對mylist進行了永久性的從小到大排序,然后用內置函數reverse把整個列表的元素的順序全部反過來。也就是說,對mylist使用了reverse函數后,最后一個元素變成了第一個元素,倒數第二個元素變成了第二個元素,依此類推。和sort函數相同,reverse函數的反轉操作也是永久性的。在sort函數的括號中可以填入其他函數并按照函數內部規定的方法排序,如圖1.19所示。

圖1.19 從大到小排序
1.3.4 列表內置函數
除了前面幾節講到的append、insert、remove等內置函數,列表還有很多其他非常實用的內置函數。
首先要講的是len函數。函數的名字“len”其實是英文單詞length的縮寫。length是長度的意思,顧名思義,這個函數是用來求列表的長度的。下面是一段使用len函數的例子:
01 mylist=[2,3,5,29,13,17,19]
02 L=len(mylist)
03 print(L)
運行程序,輸出結果為:
7
函數len的使用格式是len(列表名),它會返回列表的長度,也就是列表里元素的個數。在上面的程序中,列表的長度是7。由于len函數有返回值,所以如果你想多次使用它,最好用一個變量存儲它的值。如果只是想要輸出,可以忽略第2行,直接調用print(len(mylist))就可以了。
接下來要了解的是max函數和min函數。這兩個函數可以找出列表中的最大值和最小值:
01 mylist=[2,3,5,29,13,17,19]
02 print(max(mylist),min(mylist))
運行以上程序,輸出結果為:
29 2
同樣,如果想要多次使用max函數或min函數返回的值進行計算,也要用一個新的變量存儲它們的值。
第4個要介紹的函數是count,它是用來統計指定元素在指定列表中的出現次數的函數:
01 mylist=[2,3,5,29,13,17,19,2,2,3]
02 print(mylist.count(2),mylist.count(3),mylist.count(19))
運行以上程序,輸出結果為:
3 2 1
count函數的使用格式為:列表名+句點+函數名(count)+括號(括號內為需要統計出現次數的元素的值)。可以看到,在列表mylist中,值為2的元素有3個,值為3的元素有2個,值為19的元素有1個,所以 count函數的返回值分別為3、2、1。如果指定元素在列表中不存在,那么count函數的返回值為0。
第5個函數是index函數,它可以在列表中找出與指定值匹配的第1個元素的索引位置。
01 mylist=[6,2,8,7,2,3,4]
02 print(mylist.index(2))
運行以上程序,輸出結果為:
1
根據前面講到的幾個內置函數的規律,index函數也有返回值,使用格式也和count函數相似,括號內是需要查找的元素的值。在列表mylist中,第一個值為2的元素是第2個元素,也就是說,索引是1,所以index函數返回了1。即使索引為4的元素的值也是2,但是由于它并不是第一個匹配的元素,所以index不會返回它的值。
第6個函數是clear函數,它可以把列表清空:
01 numbers=[1,2,3,4,5,6]
02 numbers.clear()
03 print(numbers)
運行以上程序,輸出結果為:
[]
clear函數的使用格式為:列表名+句點+clear()。clear函數不需要額外的數據。
最后要講到的函數是copy函數,copy函數的功能是復制原有的列表。
說到復制列表,大家心里應該已經有了一些不用這個函數也可以進行復制的思路:
01 numbers=[1,2,3,4,5,6]
02 copylist=numbers
03 print(numbers,copylist)
這段程序的輸出結果為:
[1,2,3,4,5,6][1,2,3,4,5,6]
輸出結果一樣,是不是就復制成功了呢?
我們來看看對復制完的列表中的元素進行改動會如何:
01 numbers=[1,2,3,4,5,6]
02 copylist=numbers
03 copylist.pop()
04 print(numbers,copylist)
輸出結果為:
[1,2,3,4,5][1,2,3,4,5]
你會發現,只移除了 copylist 列表的最后一個元素,可是 numbers 列表的最后一個元素也被移除了。如果復制成功,兩個列表應該是兩個互不影響的個體,這又是為什么呢?
這是因為Python中列表存儲的方法和其他語言中的不太一樣,列表中的元素在計算機的存儲空間中占據一定的內存,而列表本身存儲的是這些元素的存儲地址,在調用列表元素的時候根據地址來調出它們原本的值。如果直接給新的列表賦值,只是復制了原來列表存儲的地址,所以元素本身并沒有被復制成兩份,如圖1.20所示。

圖1.20 復制列表
要復制元素本身就需要使用內置函數copy:
01 numbers=[1,2,3,4,5,6]
02 copylist=numbers.copy()
03 copylist.pop()
04 print(numbers,copylist)
運行這段程序,輸出結果為:
[1,2,3,4,5,6][1,2,3,4,5]
copy函數返回的是復制原列表中的元素后產生的一組新元素的存儲地址,其被存儲在新的列表中。這樣,修改復制后的列表中的元素就不會影響到原來的列表了,如圖1.21所示。

圖1.21 copy函數的效果
1.3.5 截取和拼接列表
當只需要使用列表的一部分或想把兩個列表合并成一個時,可以對列表進行截取和拼接操作。下面是對列表進行截取操作的演示程序:
01 numlist=[2,3,4,6,1,3,5,7,9,10,22,18,31,24,53]
02 print(numlist[:5],numlist[2:5],numlist[5:])
運行程序,輸出結果為:
[2,4,3,6,1][4,6,1][3,5,7,9,10,22,18,31,24,53]
截取操作過程如圖1.22至圖1.24所示。

圖1.22 完整的列表numlist

圖1.23 numlist[:5]

圖1.24 numlist[2:5]
截取列表的方式為:列表名+[m:n],其中 m 必須小于 n,否則截取到的列表為空。截取到的元素范圍為列表中索引值從m到n-1的元素。如果沒有填寫m,則m默認為0,也就是從列表的開頭截起,如果n沒有填寫則n默認為列表的長度(len(列表名)),也就是截取到列表的結尾。
列表也可以被拼接:
01 numlist=[2,3,4,6,1,3,5]
02 newlist=numlist[:5]+numlist[2:5]
03 print(newlist)
運行程序,輸出結果為:
[2,3,4,6,1,4,6,1]
拼接操作如圖1.25所示。

圖1.25 截取的列表片段相加
新的列表是舊的兩個列表拼接起來得到的,這兩個列表可以用截取的方式截出,也可以是一個列表變量或者函數返回的列表。和直接賦值不同,對拼接得到的列表進行改動不會影響原來的兩個列表。
1.3.6 字符串、元組和列表
這三種變量類型其實有很多相似之處。在講解這些相似處之前,我們先來了解元組這種變量類型。
元組和剛剛學習的列表十分相似,它們都是Python五種標準變量類型中的一種,也同樣是序列類型的變量,即由有序排列的空、單個或多個元素組成的變量,它們內部的元素都可以被調用,元素的種類可以不同。它們的不同之處在于,元組中的元素是固定不變的,它們的值不能被更改。元組的長度也是固定的,即不能添加或刪除元素。
我們使用小括號來定義元組。元組和列表一樣,可以進行拼接和截取:
01 numtuple=(2,4,6,8,10)
02 print(numtuple)
03 newtuple=numtuple*2
04 print(newtuple)
05 print(newtuple[2:5])
運行程序,輸出結果為:
(2,4,6,8,10)
(2,4,6,8,10,2,4,6,8,10)
(6,8,10)
程序中的第三行,numtuple*2相當于numtuple+numtuple。
元組可以被重復賦值,但是其中的元素不可以被更改:
01 numtuple=(2,4,6,8,10)
02 print(numtuple)
03 numtuple=(2,4,6,8)
04 print(numtuple)
05 print(numtuple[0])
06 #非法操作:
07 #numtuple[0]=100
08 #numtuple.append(10)
運行程序,輸出結果為:
(2,4,6,8,10)
(2,4,6,8)
2
由此可見,元組的合法操作和列表完全相同。以上程序用注釋寫出了兩個對元組非法操作的例子。如果這兩條語句不是注釋,則程序運行的時候會出錯。所以,要想修改元組內部元素,只能給元組重新賦值或者在定義元組的那一行直接修改程序。
我們熟悉的字符串其實也與元組十分相似。可以把字符串描述成由一個或多個字符組成的元組,它不能被修改,但可以被截取、拼接或者賦值。但是,字符串只能由字符構成,而元組可以由多種類型的變量構成,如圖1.26所示。

圖1.26 字符串的結構
下面的程序演示了字符串的截取、拼接功能的使用:
01 str1="abcd"
02 print(str1[0],str1[1])
03 print(str[1:3])
04 print(str1[1:3]+str1[:2])
運行程序,輸出結果為:
a b
bc
Bcab
字符串、元組和列表是可以相互轉換的。這時候要用到str、list和tuple函數,這三個函數可以返回轉換后的字符串、列表和元組。我們來看一個字符串轉換為元組和列表的例子:
01 sample="abcdefg"
02 print(list(sample),tuple(sample))
運行程序,輸出結果為:
['a','b','c','d','e','f','g']
('a','b','c','d','e','f','g')
可以看到,字符串中的每一個字符都被轉換成單個元素存儲在列表和元組中。任何字符串都可以轉換為列表和元組。
再來看看列表轉元組、元組轉列表以及列表和元組轉字符串的例子:
01 list1=["abcdefg","hijk"]
02 tuple1=(1,2,3,4,5)
03 print(tuple(list1),list(tuple1))
04 print(str(list1),list(tuple1))
05 del list1[0]
06 tuple=(1)
07 print(str(list1),str(tuple))
運行程序,輸出結果為:
('abcdefg','hijk')[1,2,3,4,5]
['abcdefg','hijk'](1,2,3,4,5)
hijk
1
可以看出,列表和元組相互轉換沒有任何問題,而元組和列表轉字符串時會有不同的情況出現。當列表或元組內有多個元素時,它們轉成的字符串中會包括定義時輸入的所有字符,包括中括號、小括號、逗號和用于表示字符串的引號。當列表或元組內只有一個元素時,這個元素會轉成正常的字符串,不包含中括號或小括號或者用于標記字符串的引號。
1.3.7 用循環遍歷列表
如果想要把列表中的值依次拿出來使用或者依次輸入,可以用for循環遍歷列表。
先來看一道題目:寫一段程序,讓用戶把整數輸入到列表中,再把列表內的整數全部相乘。
首先,編寫一段程序讓用戶輸入數字,并把它們加入列表:

運行程序,自己輸入一些數據,對照輸出結果檢查程序是否正確。
然后,繼續編寫程序,把整個列表中的數相乘。


運行程序,輸入數據,檢查輸出結果是否符合預期。
由于任何數乘0都等于0,所以result的初始值只能為1。同時,由于列表內元素的下標從0開始到長度減1,所以可以直接用range(total)來設定循環范圍。
這道題還有另一種做法:

這段程序的運行結果與上一段相同,但讓列表內數據相乘的方法卻不同。i循環的范圍是列表numbers,那么i每一次循環時的值就是列表中的某個元素:第1次循環時i==numbers[0],第2次循環時i==numbers[1]等。這樣,每次循環直接把result乘上i就可以了。
1.3.8 字典簡介
字典也是Python五種基礎變量類型中的一種,它和列表一樣,可以同時存儲多個任意類型的元素,所以放在列表這里進行講解。但是,比起相同之處,它和列表的不同之處更多。現實中的字典,比如英漢詞典,是用來根據英語單詞來找它對應的中文釋義的,而Python中的字典是根據輸入的關鍵字在內部尋找對應的值并返回,如圖1.27和圖1.28所示。

圖1.27 字典

圖1.28 字典中元素的調用和順序及大小無關
就像列表使用中括號,元組使用小括號一樣,定義字典或給變量賦值字典時使用大括號{}。
通過下面這一段程序來了解元組的定義和使用。

運行這段程序,輸出結果為:
{1:'a',2:'b',4:'d',3:'c','a':123}
b d 123
定義字典時,每個元素叫作一個鍵值對,用x:y的形式定義,其中x為每個元素的關鍵字,也就是鍵;y 為元素儲存的值。鍵在字典中必須是唯一且不可變的,而不同鍵代表的值可以是任意數據類型,也可以有相同的值存在。
使用字典時,和列表不一樣,在中括號的內部輸入的不是元素的索引值,而是元素的鍵。比如,鍵2所對應的值是字符串"b",那么輸出letters[2]就是輸出"b"的意思;同理,鍵4和鍵"a"也是一樣的。如果中括號內的鍵在字典中不存在,那么程序會報錯。想要更改鍵所對應的值,方法為:比如letter[4]="m",這樣鍵4所對應的值就從之前的"d"變為了"m"。
也可以在字典中添加新的元素,但方法和我們之前了解的有點不同。添加新元素的辦法是添加新的鍵,不需要使用append函數:
01 letters={1:"a",2:"b",4:"d",3:"c"} #給字典定義一個初始值
02 letters[5]="e" #給字典加入新的元素(鍵值對)
03 letters["abc"]=6
04 print(letters) #輸出字典
運行程序,輸出結果為:
{1:'a',2:'b',4:'d',3:'c',5:'e','abc':6}
用程序中的這種格式編寫代碼,新的鍵值對就會自己出現在字典中了。
可以對列表使用的函數len、del、clear和copy等,對字典也可以使用,方法是相同的。它還有更多的功能等待你去了解。
- UI設計基礎培訓教程
- Spring Boot 2實戰之旅
- JavaScript全程指南
- Machine Learning with R Cookbook(Second Edition)
- Java程序設計:原理與范例
- Java EE 7 Performance Tuning and Optimization
- 計算機應用基礎教程(Windows 7+Office 2010)
- Learning Hadoop 2
- Raspberry Pi Robotic Blueprints
- Python大學實用教程
- ABAQUS6.14中文版有限元分析與實例詳解
- Clojure for Finance
- Android 5從入門到精通
- Python程序設計教程
- Python網絡運維自動化