KT 的 Python 進階程式設計

W06|把資料留下來:一維串列的存取與寫入

今天完成後,我可以

  1. 使用中括號建立一個一維串列,並理解索引從0開始。
  2. 根據座號、月份等題意資料,換算出正確的串列索引。
  3. 使用資料[索引]讀取內容,也能把新資料寫入指定位置。
  4. 題目編號從1開始時,能判斷是否多保留第0格,讓編號與索引對齊。
  5. 用for迴圈依序存取串列中的多筆資料,並把程式分成輸入、處理與輸出三個階段。

一、教師示範與課中跟做

1-1|b022 成績公布(40分)

數學用下標表示位置,例如\(L_1\)、\(L_2\)、\(L_3\)⋯⋯;Python用中括號寫索引。

L只是我們替串列取的變數名稱,不是Python規定的寫法。

先猜,再執行:

Python 3圖片

依序試print(L[2]) → print(L[3]) → print(L[0]) → print(L[5])。哪個取到第一筆?哪一次出錯?

接著回到b022。10位同學的成績依座號是85、35、65、27、68、94、20、100、58、78。前五筆可以這樣放:

前五筆成績的兩種配置:第一種在索引0到4依序存放85、35、65、27、68;第二種保留索引0,在索引1到5存放相同成績。

選一種配置,再決定輸入座號p後要查詢哪個索引。

看教師示範時,只要追蹤四個問題:

  1. Python串列的第一格,索引是多少?
  2. 你選擇把1號同學的成績放在L[0]還是L[1]?
  3. 輸入座號p後,L[____]應填什麼,才能和你的配置一致?
  4. 你的串列總共有幾格?L[10]在你的配置中能不能存取?

依你選擇的配置,完成查詢骨架:

Python 3圖片

兩種配置的Python索引都從0開始;串列怎麼建立,查詢時就要用相同的對應方式。

同一個中括號,也能指定要修改的位置

完成查詢後,先猜哪個數字會被改掉,再執行觀察:

Python 3圖片

L[2]寫在print()裡是讀取該位置;寫在等號左邊,則是修改該位置。

看見IndexError時

如果索引超出串列範圍,Python會顯示IndexError。先檢查你的串列建立了幾格,再確認要存取的索引有沒有超出最後一格:不保留第0格時最後索引是9;多保留第0格時最後索引是10。

二、一維串列基本操作速查表

忘記寫法時,先從「現在要建立、讀取、修改、輸入還是輸出」判斷要查哪一列。本週只整理固定長度串列會用到的基本操作。

2-1|建立、存取與修改

以下用i表示要存取的索引(位置)。

表格可左右滑動
想做的事 Python寫法 意思
直接建立已知資料 L = [85, 35, 65] 依照寫入順序建立3格資料
建立n格 L = [0] * n 建立索引0到n - 1的n格
讀取一格 score = L[i] 把指定位置的資料讀入score
修改一格 L[i] = score 把score寫入指定位置
輸出一格 print(L[i]) 只輸出指定位置的資料
暫時查看整個串列 print(L) 用來除錯;會出現中括號與逗號,通常不能直接當成題目答案

2-2|用同一個程式輸入與輸出n筆資料

按「播放」或「下一步」,觀察依序輸入4、95、67、88、76時,程式如何先將成績寫入串列,再逐格讀取並輸出。動畫中的i代表目前的索引位置,縮排處都使用4格空白。

第一個for把每筆輸入寫入L[i];第二個for讓i從0重新開始,讀出L[i]並逐行輸出。

三、課中獨立練習

3-1|b020 成績公布-2(60分)

b022的10筆成績原本就寫在程式中;這一題改成由輸入提供n筆成績。因為資料之後還要依座號查詢,不能只處理完就丟掉,必須把每筆成績保存下來。

延續b022的兩種配置:你要把1號同學的成績放在索引0,還是保留第0格、放在索引1?先選好,再讓建立格數、迴圈範圍、寫入索引與查詢索引互相配合。

Python 3圖片

用座號1與n試查詢:各自應讀到哪一格?

提示:檢查你的配置

第一筆與最後一筆分別寫到哪個索引?迴圈是否剛好讀入n筆?查詢時,座號p和索引是否需要換算?

每筆輸入都要寫進串列

每次input()讀到的成績,都要指定給L[...]的一格,才能在後面依座號查詢。

四、解題後整理

讀取與寫入只差在等號中的位置

Python 3圖片

請把等號讀成「將右邊的值放進左邊」。先確認這一行真正想改變的是一般變數,還是串列中的某一格。

根據題意選擇索引方式

如果資料只需要依序存放與走訪,可以準備n格,使用索引0到n - 1:

Python 3圖片

如果題目反覆使用1到n的座號、月份或編號,可以多保留第0格:

Python 3圖片

Python仍然有索引0,只是第二種配置刻意不使用它,換取「題目編號等於串列索引」。

五、課後挑戰

課後題可以查閱講義、互相討論或尋找資料,主要目的是嘗試把本週方法延伸到不同情境;課堂中的b022與b020才是本週主要的現場練習。建議先完成a062與b023,再依時間與狀況挑戰a066和b021。

表格可左右滑動
題目 配分 定位 本週目標
a062 這個月有幾天 20分 主要練習 把月份轉成索引,讀取固定串列中的一筆資料
b023 算平均-串列版 20分 主要練習 先保存全部成績,再用第二個迴圈計算總和
a066 今年的第幾天 30分 進階挑戰 用迴圈讀取前面月份的天數並累加
b021 誰是學霸-索引挑戰 30分 進階挑戰 只記錄目前最高分所在的索引

5-1|a062 這個月有幾天(20分)

先把平年每個月的天數按照順序放進串列。這題可以在最前面多放一個0,讓month_days[1]直接代表1月、month_days[2]直接代表2月。這次請使用串列查表,不要寫12個月份的if或elif。

提示:月份如何換成索引?

第0格保留不用後,月份可以直接當成索引。請確認這個串列總共應該準備幾格。

共用工具|把程式分成Input、Process、Output

程式不外乎是三個階段:

資料/示意
Input 輸入 → Process 處理 → Output 輸出

還沒使用串列時,資料筆數很多或不固定,通常只能一邊輸入、一邊處理:

Python 3圖片

學會串列後,可以先把輸入全部留下,再分開處理:

思考步驟
Input:把所有資料存進串列
→ Process:使用串列中的資料計算答案
→ Output:輸出題目要求的結果

b023與b021都先把成績存進串列,再以不同的Process處理。b021可以沿用從索引0存放的方式,也可以保留第0格;走訪範圍與最後輸出的座號要和選擇的配置一致。

5-2|b023 算平均-串列版(20分)

這題在W04已經做過,當時每輸入一筆就直接加入總和。這次即使JMJ已顯示AC,也請重新寫一個串列版本:

注意:這不是單純重做舊題。 後面的題目會要求先算出平均,再回頭逐筆判斷資料;如果資料沒有先存進串列,就無法進行第二輪處理。請務必依照本次要求,使用兩個迴圈完成串列版。

思考步驟
Input:第一個迴圈輸入所有成績並寫入串列
→ Process:第二個迴圈從串列讀取每筆成績並累加,再計算平均
→ Output:輸出平均

本次不使用sum(),重點是練習把資料完整保存後,再次走訪使用。

需要時展開:兩階段骨架
Python 3圖片
完成後補充:加總的簡寫

下面兩種寫法意思相同,只選一種,不要連續執行兩行。空格代表本次要加的數值。

完整指定寫法:

Python 3圖片

簡寫:

Python 3圖片

現階段先用完整指定寫法練習加總。簡寫看得懂即可,不要求使用。

5-3|a066 今年的第幾天(30分)

這題只需要讀取月份天數,不需要修改串列。先將答案設為當月日期,再把「目標月份以前」的每個月天數加進答案。

例如5月8日需要累加1月、2月、3月、4月,再加上8日;不能把5月的全部天數也加進去。

提示一:讀取同一行的月份與日期

以下兩種寫法擇一使用。沿用W03的寫法:

Python 3圖片

或使用精簡寫法:

Python 3圖片

精簡寫法中的map(int, ...)會把切開的兩份資料轉成整數,交給month與day。

提示二:決定迴圈終點

如果輸入1月,前面沒有任何月份,迴圈應執行0次;如果輸入5月,迴圈應依序讀取1月到4月的天數。

5-4|b021 誰是學霸-索引挑戰(30分)

這題在W05曾用max_score與座號兩個變數完成。這次先把所有成績存進串列,再改成只記錄「目前最高分所在的索引」。你可以從索引0存第一筆,也可以保留第0格;最後依自己的配置輸出座號。

注意:請不要直接交回W05的舊程式。 後續的搜尋與排序會經常需要記錄「某個值位於哪一格」,再用索引回到串列取得或修改資料。請務必練習只記錄最佳位置,並透過索引讀取對應成績。

處理最高分時,只用一個變數記錄目前冠軍的索引,不另外保存最高分。

提示一:最高分不必另外保存

如果目前冠軍的索引記在best_i,它的成績可以隨時用下列寫法取得:

Python 3圖片
提示二:用成績比較,記錄最佳索引

初始冠軍要選哪位同學?迴圈要從哪位同學開始比較?找到更高分時,要更新同學的索引,還是分數?

Python 3圖片

六、完成後自我檢查