函式
給一段程式取個名字,之後就叫得動它。 · ⏱ 約 30 分鐘
你會學到三件事
def 定義一個函式
- 參數進去、回傳值出來
- 函式裡面的變數只活在裡面
開始之前
第 2 課你給一個值取了名字。這一課要給一段程式取名字。
而你其實一直在用別人寫好的:print、len、input、int 都是函式。
🟢 先把編輯器打開,跟著下面一起做:跟著做
一、def
照著打上這一段:
1def add(a, b):2 return a + b3 4print(add(3, 4)) # 7
def add(a, b):
↑ ↑ ↑ ↑
關鍵字 名字 參數 冒號(和 if / for 一樣)
return a + b
└─ 縮排 = 函式的身體
⚠️ 函式要先定義才能用,定義寫在呼叫的後面會 NameError。
積木盤上這一顆寫著「定義函式 …」。
二、return
return 同時做兩件事:
- 把值交出去
- 立刻結束這個函式,後面的行不會跑
🔎 這一段是試一下——打了看結果就好,不要留在程式裡。
1def f(n):2 return n3 print("印不出來") # ← 永遠不會跑
沒有 return 的函式回傳 None:
1def greet(name):2 print("你好," + name)3 4x = greet("小明")5print(x) # None
⚠️ 這是一個常見的困惑:「印出來」和「交出去」是兩件不同的事。
|
給誰 |
print(x) |
給人看 |
return x |
給呼叫它的那段程式用 |
三、參數可以有預設值
參數後面加上 =,不給的時候就用那個值:
🔎 這一段是試一下——打了看結果就好,不要留在程式裡。
1def greet(name, greeting="你好"):2 print(greeting + "," + name)3 4greet("小明") # 你好,小明5greet("小明", "早安") # 早安,小明
⚠️ 有預設值的參數要放後面。 def f(a=1, b) 是語法錯誤。
四、🔴 裡面的變數只活在裡面
函式裡面取的名字,外面看不到:
🚫 這一段是反例——課文在說不要這樣寫,別照著拉。
1def f():2 x = 103 print(x)4 5f()6print(x) # 💥 NameError:外面沒有 x
函式裡宣告的變數叫區域變數,函式結束它就消失了。
好處是:你在函式裡取什麼名字,都不會撞到外面的東西。
⚠️ 反過來,函式讀得到外面的變數,而改不到:
🚫 這一段是反例——課文在說不要這樣寫,別照著拉。
1total = 02def add():3 total = total + 1 # 💥 UnboundLocalError
要改外面的東西,正確的做法是回傳它:
🔎 這一段是試一下——打了看結果就好,不要留在程式裡。
1def add(total):2 return total + 13 4total = add(total)
(有個 global 關鍵字可以強行改,而幾乎永遠不該用它。)
五、為什麼要寫函式
① 同一段程式要用好幾次 → 不用複製貼上
② 一段程式做的事需要一個名字 → 讀的人不必看細節
③ 可以單獨測試那一小段 → 出錯時範圍小
函式不是「進階語法」——它是你第一次覺得
「這幾行我不想再寫一遍」的時候,自然會想要的東西。
完成的樣子
這一課的參考做法——程式碼每一行的號碼,就印在對應的那塊積木上。
1def add(a, b):2 return a + b3 4def greet(name):5 print("你好," + name)6 7print(add(3, 4))8greet("小明")
把積木打散,自己排回去:排回去:把剛才那支程式的積木排好
換你了
寫一個 is_leap(year),回傳 True 或 False(第 5 課那個閏年規則)。
⚠️ 要 return,不要 print,這樣它才用得進 if is_leap(2000):。
到編輯器做這一題:練習:寫一個 is_leap(year),要 return 不要 print
做一個
寫兩個函式算最大公因數:一個用迴圈,一個叫自己(遞迴)。兩個答案都印出來。
輾轉相除法只有一句話:gcd(a, b) = gcd(b, a % b),而 b 變成 0 的時候答案就是 a。
⚠️ 裁判用的是 48 和 18。哪一個版本比較好讀?跟旁邊的人不一定同答案。
到編輯器做這一題:做一個:最大公因數,兩種寫法
這一課你做了什麼
- 你用
def 定義了兩個函式
- 你分得出
print(給人看)和 return(交出去)
- 你知道函式裡的變數只活在裡面
如果卡住了
| 你看到 |
多半是因為 |
NameError: add |
函式定義寫在呼叫的後面了 |
函式回傳 None |
少了 return |
UnboundLocalError |
在函式裡改了外面的變數。改成回傳它 |
TypeError: missing argument |
呼叫時參數個數不對 |
| 函式印出來了卻不能拿來用 |
print 不是 return |
在編輯器打開這一課 →