Semorphe

函式與例外

定義函式,以及讓錯誤變成一條可以走的路。 · ⏱ 約 35 分鐘

你會學到三件事

  1. def:不用寫回傳型別,而可以有預設值
  2. lambda*args
  3. try / except:錯誤不是當機,是一條分支

開始之前

C++ 的函式要寫回傳型別和每個參數的型別。 Python 兩個都不用——而換來的是你要自己知道

一、def

def add(a, b=1):
    return a + b

print(add(3))         # 4   ← b 用預設值
print(add(3, 4))      # 7

b=1預設值:呼叫時不給就用它。

⚠️ 有預設值的參數要放在後面。 def f(a=1, b) 是語法錯誤。

⚠️ 預設值不要用 listdef f(items=[]))——那個 list 是所有呼叫共用同一個, 而不是每次新的。這是 Python 最有名的一個坑,先知道有這件事就好。

二、*args:數量不定

def total(*args):
    return sum(args)

print(total(1, 2, 3))     # 6

*args 把「傳進來的所有東西」收成一個 tuple。

sum() 是內建的——Python 有很多這種內建函式len max min sorted sum), 遇到「我想做某件很常見的事」時,先查一下有沒有。

三、lambda:一次性的小函式

double = lambda x: x * 2
print(double(5))          # 10

它就是一個沒有名字的 def,而只能寫一個運算式

它的用處在「把一個函式當參數傳進去」:

sorted(names, key=lambda s: len(s))     # 依長度排序

⚠️ 不要用 lambda 取代 def 上面那個 double = lambda x: ... 其實應該寫成 def double(x): return x * 2——一樣長,而好讀又好除錯。

四、try / except

try:
    n = int("abc")
except ValueError:
    print("轉換失敗")

int("abc") 轉不出來,於是它丟出一個 ValueError

沒有 try 的話程式當場停掉;有的話,except 那一段接住它,程式繼續走。

意思
try: 這一段可能會出事
except ValueError: 出的是這種事的話,做這個
else: 都沒出事的話(少用)
finally: 不管有沒有出事都要做(關檔案之類)

⚠️ 不要寫光禿禿的 except: 那會連你按 Ctrl+C 都接住, 而且會把你自己的打字錯誤一起吞掉——一個接住所有錯誤的程式, 與一個沒有錯誤的程式看起來一樣。

例外不是「錯誤處理」,是「另一條路」。 檔案不存在、使用者打錯字、網路斷了——這些本來就會發生, 它們不是 bug,是你的程式該想過的情況。

完成的樣子

def add(a, b=1):
    return a + b

def total(*args):
    return sum(args)

print(add(3))
print(add(3, 4))
print(total(1, 2, 3))

double = lambda x: x * 2
print(double(5))

try:
    n = int("abc")
except ValueError:
    print("轉換失敗")

換你了

寫一個函式,讀進使用者輸入並轉成整數——打錯字的話要求他重打, 而不是當掉。

提示:while True:try + 成功就 return

這一課你做了什麼

如果卡住了

你看到 多半是因為
SyntaxError: non-default argument follows default 有預設值的參數要放後面
例外沒被接住 except 的型別不對。先寫 except Exception as e: print(e) 看看是什麼
函式回傳 None 少了 return。Python 不寫 return 就回 None
預設值 list 每次呼叫都變長 那個經典的坑。預設寫 None,進函式再建新的
在編輯器打開這一課 →