函式
函式是把一段程式包起來、取個名字,之後要用就呼叫它,不必一直重寫。這一章看怎麼定義函式、傳資料進去、把結果拿回來。
用 def 定義函式:def 後面接名字和一對括號,底下縮排的就是函式的內容。定義好之後,寫「名字加括號」就能呼叫它:
def greet(name): print("你好," + name)
greet("小明")括號裡的 name 是參數,呼叫時給的 "小明" 會被塞進去。按「下一步」時注意,呼叫 greet 那一刻,右邊的呼叫堆疊會多出一層,跳進函式裡執行。
回傳值:return
Section titled “回傳值:return”前面的 greet 只是印東西。更常見的是讓函式算出一個結果交回來,用的是 return:
def add(a, b): return a + b
result = add(3, 5)print(result)add(3, 5) 執行到 return a + b,就把 8 交回呼叫的地方,存進 result。函式一旦 return,就結束、跳回原來的位置。
return 也可以一次回傳好幾個值,用逗號隔開;接收時同樣用逗號一次拆開:
def divide(a, b): return a // b, a % b
quotient, remainder = divide(17, 5)print("商是", quotient)print("餘數是", remainder)return a // b, a % b 一口氣把商和餘數都交回來,quotient, remainder = divide(17, 5) 再一次接住兩個。
參數的預設值
Section titled “參數的預設值”參數可以給預設值。呼叫時沒提供,就用預設的;有提供,就用你給的:
def greet(name, greeting="你好"): print(greeting + "," + name)
greet("小明")greet("小美", "早安")greet("小明") 沒給 greeting,用預設的「你好」;greet("小美", "早安") 則把預設值蓋掉。
位置引數與關鍵字引數
Section titled “位置引數與關鍵字引數”呼叫時給的值叫引數。可以照順序給(位置引數),也可以指名道姓給(關鍵字引數):
def describe(name, age): print(name, "今年", age, "歲")
describe("小明", 18)describe(age=20, name="小美")describe("小明", 18) 靠位置對應,第一個給 name、第二個給 age。describe(age=20, name="小美") 直接指名,這樣順序就無所謂了。
提早 return
Section titled “提早 return”return 不一定要放在最後。一遇到就可以回傳、結束函式。這常拿來先處理特殊情況,把主要的邏輯留到後面,不用層層巢狀的 if:
def check_age(age): if age < 0: return "年齡不能是負的"
if age < 18: return "未成年"
return "成年"
print(check_age(-5))print(check_age(15))print(check_age(30))年齡是負的就直接回傳、不再往下;否則再看是不是未成年;都不是,才走到最後的「成年」。
用 None 當起始值:is None
Section titled “用 None 當起始值:is None”None 是一個特別的值,代表「還沒有值」。它常拿來當一個變數的起始狀態,之後再判斷「到底填了沒」。判斷一個值是不是 None,習慣上用 is None(而不是 == None):
def find_min(numbers): smallest = None for n in numbers: if smallest is None or n < smallest: smallest = n
return smallest
print(find_min([5, 2, 8, 1, 9]))這裡要自己找出最小值,一開始還沒看過任何數字,所以 smallest 先設成 None。迴圈裡 if smallest is None or n < smallest 的意思是「如果還沒記過任何數,或這個數更小,就更新」。這樣第一圈一定會先記下第一個數,之後才逐一比較。
接收任意多個引數:*args 與 **kwargs
Section titled “接收任意多個引數:*args 與 **kwargs”有時你不知道會傳幾個引數進來。參數前面加一個 *,就會把所有位置引數收集成一個元組:
def total(*numbers): result = 0 for n in numbers: result = result + n
return result
print(total(1, 2, 3))print(total(10, 20, 30, 40))total(1, 2, 3) 和 total(10, 20, 30, 40) 傳的個數不同,函式裡的 numbers 都能一次收下、用迴圈加總。
加兩個 *(**)則是把關鍵字引數收集成一個字典:
def show_info(**info): for key in info: print(key, ":", info[key])
show_info(name="小明", age=18)函式可以呼叫自己,這叫遞迴。關鍵是要有個停下來的條件,否則會無止盡地叫下去。下面用遞迴算階乘(5 的階乘是 5×4×3×2×1):
def factorial(n): if n == 0: return 1
return n * factorial(n - 1)
print(factorial(5))一直按「下一步」,看右邊的呼叫堆疊怎麼一層一層疊上去:factorial(5) 要先算 factorial(4),factorial(4) 又要 factorial(3)……一路到 factorial(0) 回傳 1,才逐層乘回來,最後得到 120。這個「堆疊疊起來又收回去」的過程,用步進看最清楚。