0基礎學Python之十三:列表(下)

0基礎學Python之十三:列表(下)

來自專欄 可樂編程 https://www.zhihu.com/video/969269426096496640

Hi 大家好,我是王可樂,今天我們繼續來聊列表相關的話題。為什麼我們要聊那麼多期的列表話題呢?這是因為,列表這個數據類型真的是太重要了,值得我們多花一點時間來理解和實踐。

好的,我們開始吧。首先,我們先來設想一個場景,假設我是一個中學的數學老師,剛剛進行了一次數學考試,我想知道這次考試的最高分,最低分,平均分。我應該怎麼用Python來解決這個問題呢?相信認真看過我們之前節目,並且有過思考和實踐的朋友們,應該很快能想到怎麼做。

scores = [57, 49, 85, 67, 50, 54, 83, 95, 94, 84, 74, 70, 63, 45, 76, 60, 89, 59, 73, 77, 54, 54, 63, 91, 97, 71, 62, 96, 66, 66, 87, 81, 60, 98, 58,78, 43, 71, 68, 58, 74, 98, 77, 67, 75, 57, 49, 44, 54, 43]min_score = 101max_score = 0sum_score = 0for i in scores: if i < min_score: min_score = i if i > max_score: max_score = i sum_score += iprint("最高分:", max_score)print("最低分:", min_score)print("平均分:", sum_score/len(scores))

剛剛學習過列表,首先我們想到可以把同學們的成績都放到一個列表中。在這段代碼里,我們用 scores 這個數組存放成績。然後,我們利用循環語句遍歷一遍這個列表,把最大值,最小值記下來,並且把總分數加起來就行了。注意看一下,我們定義的三個變數:min_score 保存最小值;max_score 保存最大值;sum_score 記錄總分數,他們定義的時候分別被賦予了不同的值。

為什麼這三個變數的初始值要這樣來設置呢?請各位同學自己思考一下原因。

對於統計成績這個場景,以上的實現方式非常直接。不過,Python 還有更加簡潔的方式來處理這個需求。我們可以直接使用 max(),min(),sum()這三個 Python 的內置函數來得到一個列表中的最大值,最小值,以及所有數字的和,所以上面的代碼可以直接簡化成這樣:

scores = [57, 49, 85, 67, 50, 54, 83, 95, 94, 84, 74, 70, 63, 45, 76, 60,89, 59, 73, 77, 54, 54, 63, 91, 97, 71, 62, 96, 66, 66, 87, 81, 60, 98, 58,78, 43, 71, 68, 58, 74, 98, 77, 67, 75, 57, 49, 44, 54, 43]print("最高分:", max(scores))print("最低分:", min(scores))print("平均分:", sum(scores)/len(scores))

怎麼樣,是不是簡潔多了?不過雖然第一段代碼比第二段代碼長,但第二段代碼的執行效率實際上是沒有第一段代碼那麼高的。具體原因與 max,min 以及 sum 這三個函數的實現機制有關,可樂將在後續演算法相關的課程中給大家解釋。

在這裡可樂想給大家解釋的一點是,寫程序實際上也是一個找平衡的過程。什麼意思呢?如,複雜的代碼可能運行效率高,但不如簡單的代碼好理解、易於維護;有的程序佔用內存多,但是運行速度快,而佔用內存少的方案,運行速度就慢,等等。這些糾結和取捨也是編程有意思的一方面。可樂建議初學編程的朋友,優先考慮保持代碼的簡潔易讀性。以大家目前使用的家用電腦的運算能力,處理的一些日常的工作,性能是足夠的。

講到這裡,可能又有頭腦靈活的朋友會問,列表不是可以包含多種數據類型嘛?上面的例子里,數組裡只有整數,如果數組裡還有字元串,那麼使用內置 max,min,sum 這三個內置函數會有什麼結果呢?我們來試一下:

>>> a = [1,2,3,"hello"] # 我們來定義一個這樣的數組>>> max(a) # 然後嘗試用 max 來計算這個數組的最大值Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: > not supported between instances of str and int

可以看到,Python 在這裡並沒有給我們帶來什麼驚喜,而是提示有錯誤。我們看報錯的信息,它說 ">" 號不支持字元串和整數之間的比較,說明 max 函數在內部使用了 ">" 號操作符來比較元素的大小。這是一個符合大家直覺的結果。

不過,我們還是可以做一些事情,讓 「>」 號支持不同類型數據之前的比較。具體的實現方法就留在可樂的高級課程中講解了。目前我們只要保證列表中的數據,數據類型相同就可以了。

知道了最高分,最低分,平均分之後,可樂老師還有一個新需求,就是對班級里的學生們的成績進行排名。排序在很多場景里是非常常見的需求。那麼,列表中的數字們怎麼排序呢?

在 Python 中,列表支持一個方便的函數 sort,只要調用一下 sort 函數,列表中的數字就會按照從小到大的順序排列好了。我們來試一下,可樂把前面代碼中的 scores 列表複製到了 Python Shell 里:

>>> scores = [57, 49, 85, 67, 50, 54, 83, 95, 94, 84, 74, 70, 63, 45, 76,... 60, 89, 59, 73, 77, 54, 54, 63, 91, 97, 71, 62, 96, 66, 66, 87, 81,... 60, 98, 58, 78, 43, 71, 68, 58, 74, 98, 77, 67, 75, 57, 49, 44, 54,... 43]>>> scores.sort() # 然後,我們輸入 scores.sort()>>> scores # 然後查看一下 scores 列表,可以看到,已經從小到大排序了呢[43, 43, 44, 45, 49, 49, 50, 54, 54, 54, 54, 57, 57, 58, 58, 59, 60, 60,62, 63, 63, 66, 66, 67, 67, 68, 70, 71, 71, 73, 74, 74, 75, 76, 77, 77,78, 81, 83, 84, 85, 87, 89, 91, 94, 95, 96, 97, 98, 98]

是不是很方便?如果你想從大到小排序,也很簡單,只要換用列表的另一個內置函數 reverse 就可以了:

>>> scores.reverse() # 輸入 scores.reverse()>>> scores # 再來看一下,這次就是從大到小排序了[98, 98, 97, 96, 95, 94, 91, 89, 87, 85, 84, 83, 81, 78, 77, 77, 76, 75,74, 74, 73, 71, 71, 70, 68, 67, 67, 66, 66, 63, 63, 62, 60, 60, 59, 58,58, 57, 57, 54, 54, 54, 54, 50, 49, 49, 45, 44, 43, 43]

接下來,可樂老師又提了一個需求,我還想知道哪些同學沒考及格,要對他們進行重點輔導。這個需求應該怎麼來實現呢?大家可以先暫停視頻,自己試試看,然後再來看答案。

好,下面可樂老師來給出一個解決方案。利用一個循環來遍歷所有的分數,然後找出低於 60 分的即可,代碼如下:

unpassed_scores = []for i in scores: if i < 60: unpassed_scores.append(i)print("不及格的分數有:", unpassed_scores)

這個程序的功能比較簡單,可樂就不多解釋了,不過雖然功能很簡單,但還是需要好幾行代碼。那麼有沒有更加方便的實現方式呢?

可樂下面要介紹的這個技巧叫做列表推導式。使用這個技巧,可以很方便地通過簡單操作生成新的列表。下面可樂就來給大家演示一下:

>>> unpassed_scores = [i for i in scores if i < 60] # 我們這樣來從 scores 列表中篩選出來低於 60 的分數>>> print("不及格的分數有:", unpassed_scores) # 然後,我們列印出來看看,和上面的結果是一樣的

怎麼樣,同樣的邏輯居然只用了一行代碼就完成了,我們來看看關鍵的這行代碼。

首先,等號右邊的部分代碼是用中括弧括起來的,就是表示列表的符號;中括弧裡面的內容,它的含義是「對於 socres 列表裡的每一個 i,只要滿足 i<60,就把 i 放到新生成的列表裡。

事實上,for 前面的 i 可以是一個靈活的表達式,我們還可以對 i 做更多的操作,例如:

>>> x = [1,2,3,4,5,6,7,8,9,10] # 我們定義一個新的列表 x>>> [i*i for i in x] # 然後用列表推導式生成一個新的列表,其中每個數都是 x 中對應數字的平方[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

這裡沒有了前面代碼 if 的部分,也就是說對於 x 列表中的每一個元素 i,都會產生一個 i*i 在新的列表中。列表推導式又是一個能夠極大簡化代碼的技巧,可樂建議大家在看了本期節目後,多多實踐,更好地掌握這個技巧。

今天的最後一個知識點,可樂要講一下字元串和列表的相互轉化。在之前講字元串的時候,可樂為大家演示過如何使用 join 函數從列表生成字元串,前提是列表中的元素都是字元串。今天可樂再來給大家介紹一下 join 函數,以及另一個 split 函數。我們還是用實例來演示一下:

>>> x = "1,2,3,4,5,6,7,8,9,0" # 首先,我們定義一個字元串,是逗號分隔的一串數字>>> xl = x.split(",") # 我們調用 split 函數,它可以以逗號為分隔符把字元串拆開成一個字元串列表>>> xl # 我們來看一下,新生成的 xl 列表如下[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]>>> nl = [int(i) for i in xl] # 使用剛剛學過的列表推導式,我們可以生成一個數字列表>>> nl # 我們來看一下,nl 里的元素全是數字[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]>>> -.join(xl) # 最後,我們再用之前見過的 join 函數,把列表重組成字元串,不過這次我們換用減號作為分隔符1-2-3-4-5-6-7-8-9-0

以上用 split 處理字元串,以及用 join 把列表組合成字元串的操作非常常見。大家要多多練習哦。

好了,今天的課程就到這裡。今天我們講到了更多的列表的特性和操作技巧。並且利用列表幫助可樂老師統計了學生的成績。你是不是已經想到了很多列表在自己工作環境里的應用場景了呢?

不過,列表只是 Python 中有用的數據類型之一,下節課我們將為大家介紹另一個有趣的數據類型。記得關注我們的公眾號「可樂編程」哦,如果你覺得課程內容比較有趣,請轉發給你的朋友們,可樂感謝大家的支持,我們下次課再見!


推薦閱讀:

anaconda 3中修改jupyter notebook自定義工作文件夾問題
切爾西隊史上第一次連續三場0比0,重點是...
為什麼關於Python的UI框架 kivy ,在中國無人問津,而且相關的書籍很少?
python高效編程實踐-如何在列表,字典,集合中根據條件篩選數據(1/50)
《Python Linux系統管理與自動化運維》收到的評價

TAG:Python | 零基礎 | 編程 |