National Yunlin University of Science and Technology
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try a Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

1

Local AI

--

Uedu Code

--

雲林科技大學 AQI 62 26°C PM2.5 12
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 09

串列(List)

有序、可變的容器:索引、切片、方法與串列生成式
Interaction實作 30 minute(s)

Learning Objectives

  • 串列(list)的宣告與運算:索引、切片、修改、結合、重複
  • 名稱與物件:別名(b = a)與複製(a[:]、a.copy())的差別
  • 串列相關的內建函數:len、max、min、sum、sorted、list
  • 串列相關的方法:append、extend、insert、pop、remove、sort、reverse、index、count
  • 串列生成式(List Comprehensions)

為什麼需要串列

一個班有 50 位同學的成績,總不能開 50 個變數 score1、score2…… 串列(list)把一串資料裝進同一個容器,用一個名稱管理,再配合迴圈一次處理全部。

串列是 Python 用途最廣的資料型態:

特性 說明 和字串比較
有順序(sequence) 每個項目有位置編號,可以用索引與切片 和字串一樣
可變(mutable) 建立後可以修改、新增、刪除項目 字串不可變
項目型態可以不同 ['ncu', 2015, 3.5, [1, 2]] 字串只裝字元

「可變」帶來方便,也帶來本課最重要的觀念:兩個名稱可能指向同一個串列。改了其中一個,另一個也會跟著變。

建立、取用與修改串列

用中括號 [ ] 建立串列,項目之間用逗號分隔。注意第 7、9、11 行:串列可以原地修改,右邊物件圖裡是同一個串列的內容在變,list1 的箭頭一直指著它。

串列的切片

串列的切片規則和字串完全一樣:nums[start:stop:step] 不包含 stop。試試看 nums[-2:]、nums[::2]、nums[::-1],再想想:nums[1:4] 和 nums[1] 有什麼不同?(一個是串列,一個是項目)

巢狀串列

串列的項目也可以是另一個串列。lst[2] 取出裡面的串列,lst[2][1] 再取出那個串列的索引 1。看物件圖:外層串列的第三格是一個箭頭,指向另一個串列。

想一想:索引與切片

1.

下面的程式會印出什麼?

lst = list("Hello Python")
print(lst[6:-2])
2.

下面的程式會印出什麼?

lst = [33, "python", [11, 12, 13], 77]
print(lst[2][-1], len(lst))
第 1 次作答

名稱與物件:別名

Module 02 說過:變數是名稱,指向記憶體裡的物件。寫 b = a 的時候,Python 不會複製串列, 只是讓 b 也指向 a 指著的那個串列。這時 a 和 b 是同一個物件的兩個名字,稱為別名(alias)。

寫法 結果 之後改 b,a 會變嗎?
b = a 兩個名稱、同一個串列 會
b = a[:] 切片複製出新的串列 不會
b = a.copy() 複製出新的串列(和 a[:] 相同) 不會
b = list(a) 用 a 的項目建立新的串列 不會

判斷是不是同一個物件,用 Module 04 的身分運算子 is。

b = a 與 b = a[:]

這是本課最重要的範例。第 3 行之後,看右邊:a 和 b 兩條箭頭指向同一個串列;第 4 行透過 b 加入 4,a 也看得到。第 10、11 行之後,c、d 各自指向新的串列,再怎麼改都不影響 a。

互動練習:b = a 之後改 b

依序按 b = a、b.append(9),看 a 有沒有跟著變。按「重來」,再試 b = a、b = b + [9]:+ 會建立新的串列,b 改指向新物件,a 就不受影響。最後試試 b = a[:]。

淺層複製:裡面的串列還是共用

copy() 和 [:] 只複製外層:新串列裡放的仍是指向原本那些內層串列的箭頭。看第 5 行:改 y[0],x[0] 也變了。要連內層一起複製,用 copy 模組的 deepcopy()。

想一想:別名與複製

1.

下面的程式會印出什麼?

a = [1, 2]
b = a
b.append(3)
print(a)
2.

下面的程式會印出什麼?

a = [1, 2]
b = a[:]
b.append(3)
print(a, b)
3.

下面的程式會印出什麼?

a = [1, 2]
b = a
b = b + [3]
print(a)
第 1 次作答

串列的函數與方法

內建函數(寫成 函數(串列)):

函數 作用
len(lst) 項目個數
max(lst) / min(lst) 最大值/最小值(項目型態要能互相比較)
sum(lst) 總和(項目要是數值)
sorted(lst, reverse=False) 傳回新的排序後串列,原串列不變
list(seq) 把字串、元組、range 等轉成串列

串列方法(寫成 串列.方法()),大多是原地修改串列本身:

方法 作用
append(x) 把 x 加到最後
extend(t) 把 t 的每個項目依序加到最後(相當於 lst += t)
insert(i, x) 把 x 插入到索引 i
pop(i) 取出並移除索引 i 的項目,預設是最後一個
remove(x) 移除第一個等於 x 的項目
index(x) / count(x) x 第一次出現的位置/出現幾次
sort() / reverse() 排序/反轉順序(傳回 None)
copy() / clear() 複製出新串列/清空

字串方法傳回新字串;串列方法多半直接改串列、傳回 None。所以 nums = nums.sort() 會讓 nums 變成 None,這是常見的錯誤。

常用串列方法

每一行執行後看右邊的串列怎麼變。注意第 15 行:sort() 把串列排好了,但傳回的 r 是 None。

串列生成式

串列生成式 [運算式 for 項目 in 序列 if 條件] 很像數學的集合寫法,例如 S = {x² : x ∈ {0..5}}。比較第 2~4 行的 for 迴圈和第 8 行的生成式:做的是同一件事(迴圈變數叫 n 或 x 都可以,名稱自己取)。

想一想:方法與生成式

1.

下面的程式會印出什麼?

nums = [3, 1, 2]
r = nums.sort()
print(r, nums)
2.

下面的程式會印出什麼?

print([x * 2 for x in range(5) if x % 2 == 1])
第 1 次作答

實作:排名但保留原始順序

要把成績由高到低排名,但原本的 scores 不能被打亂。現在的程式有一個別名的問題:執行看看,「原始」那一行也被排序了。請完成兩個 TODO:讓 ranked 成為 scores 的複本,並用串列生成式找出 80 分以上的分數(依原始順序)。

你的輸出
預期輸出

重點精華回顧

  • 串列的特性:有順序、可變、項目型態可以不同;用索引、切片取用與修改,+ 結合、* 重複、in 檢查成員。
  • 別名與複製:b = a 是同一個串列的兩個名稱;a[:]、a.copy()、list(a) 才會複製出新串列。copy() 是淺層複製,巢狀串列要用 copy.deepcopy()。
  • 內建函數:len、max、min、sum、sorted(傳回新串列)、list。
  • 串列方法:append、extend、insert、pop、remove、index、count、sort、reverse;會修改串列的方法傳回 None。
  • 串列生成式:[運算式 for 項目 in 序列 if 條件],用一行取代「空串列+for+append」。
這一課完成了!
Next lesson:元組(Tuple)
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。