Semorphe

推導式

把一個迴圈壓成一行。 · ⏱ 約 30 分鐘

你會學到三件事

  1. [... for ... in ...] 一行做出一個新的 list
  2. 加上 if 就是篩選
  3. 什麼時候不該用它

開始之前

這個形狀在 Python 裡到處都是:

squares = []
for n in nums:
    squares.append(n * n)

四行,而它只做一件事:「把每一個都換成別的」。

🟢 先把編輯器打開,跟著下面一起做:跟著做

一、換成別的

一行把一串換成另一串:

1squares = [n * n for n in nums]
變數n變數n×變數nums收集對每一個n取自只留,再外面一層設定squares為1

從右邊往左邊讀:

[  n * n     for n in nums  ]
   ↑             ↑
 每一個變成    走過 nums 的每一個 n

nums 是 [1,2,3,4,5] 的話,squares 就是 [1,4,9,16,25]。

⚠️ 它做出一個新的 list,不會改到原來的。

二、加上篩選

後面加一個 if,就只留下合的:

1evens = [n for n in nums if n % 2 == 0]
變數n變數nums變數n2取餘數0=收集對每一個n取自只留,再外面一層設定evens為1

if 放在最後,意思是「只留下符合的」→ [2, 4]。

兩件事可以一起做:

🔎 這一段是試一下——打了看結果就好,不要留在程式裡。

1[n * n for n in nums if n % 2 == 0]     # [4, 16]
變數n變數n×變數nums變數n2取餘數0=收集對每一個n取自只留,再外面一層1

讀法:「走過每一個 n,如果是偶數,就換成 n * n」。

三、dict 也可以

換成大括號就是一本字典:

1table = {n: n * n for n in nums}2# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
變數n變數n變數n×變數nums收集 鍵對應取自只留對每一個n註解{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}設定table為12

差別只在大括號和那個冒號——和第 4 課分辨 dict / set 的方式一樣。

四、⚠️ 什麼時候不該用

推導式讀起來像一句英文,而那只在它短的時候成立。

下面這個寫法不要學——它塞了太多件事:

🚫 這一段是反例——課文在說不要這樣寫,別照著拉。

1# 🔴 不要這樣2r = [f(x) for row in grid for x in row if g(x) and h(x) or k(x)]
變數x呼叫f變數row變數x呼叫g變數x呼叫h而且變數x呼叫k或者變數grid對每一個row取自,再外面一層收集對每一個x取自只留,再外面一層設定r為註解🔴 不要這樣12

判準:

情況 用什麼
一個 for、最多一個 if ✅ 推導式
兩層以上的 for ⚠️ 想一下
裡面有 if / else 又有篩選 🔴 寫成迴圈
你要在裡面 print 或改東西 🔴 那不是推導式該做的事

推導式是「把一串變成另一串」的寫法。 它不是「用比較少的字寫迴圈」的寫法。

完成的樣子

這一課的參考做法——程式碼每一行的號碼,就印在對應的那塊積木上。

1nums = [1, 2, 3, 4, 5]2squares = [n * n for n in nums]3print(squares)4evens = [n for n in nums if n % 2 == 0]5print(evens)6table = {n: n * n for n in nums}7print(table)
12345串列變數n變數n×變數nums收集對每一個n取自只留,再外面一層變數squares變數n變數nums變數n2取餘數0=收集對每一個n取自只留,再外面一層變數evens變數n變數n變數n×變數nums收集 鍵對應取自只留對每一個n變數table印出設定table為印出設定evens為印出設定squares為設定nums為1234567

換你了

給一串名字,做出「每個名字的長度」的 list。

再做一個進階的:只留下長度大於 3 的名字。

到編輯器做這一題:練習:每個名字的長度,以及只留長度大於 3 的

做一個

做出 1 到 20 的平方,印出有幾個;再篩出其中的偶數,印出那一串。

🔴 兩行都要是推導式。做完之後用 for 迴圈寫一次同樣的東西, 然後問自己:哪一份比較好讀?而它的答案跟行數沒有關係。

到編輯器做這一題:做一個:平方數裡的偶數

這一課你做了什麼

如果卡住了

你看到 多半是因為
SyntaxError for 和 if 的順序錯了。if 在最後
拿到的是 <generator ...> 用了小括號。list 要方括號
原來那串也被改了 不會——推導式一定做新的。改到的話是別處
想在裡面 if/else 換值 那要寫成 [a if 條件 else b for ...]——位置不一樣
在編輯器打開這一課 →