目前為止介紹的函式,都是 Python 事先提供的函式,但我們也可以自己撰寫函式。透過函式,可以將程式碼中常用的功能包裝起來,重複的呼叫與執行,使得功能更容易重複使用,程式碼更容易管理(當然,為了簡潔,本篇章的範例可能簡單到不使用函式必較方便)。下面的程式,會簡單的將變數值 +1 之後再回傳:
def my_add(x): return x + 1 a = 3 a = my_add(a) print("(1st call) New a:", a) a = my_add(a) print("(2nd call) New a:", a) a = my_add(a) print("(3rd call) New a:", a)在上述範例中:
- 第一行的 def 是「定義」的意思,代表要開始定義一個函式,在它後面有縮排進去的,都是函式內容。
- 「my_add」是函數名稱,命名規則與變數相同。
- 小括號內,則是函式的輸入參數列表,輸入參數可以有不只一個。
- 在函式裡面,可以寫上任何需要的敘述,如果需要回傳運算結果的話,記得使用「return」。
- 呼叫函式的方法,如第 5 行所示,與呼叫 Python 提供的函式相同。
當你需要傳入兩個以上的參數時,中間以逗點區隔即可。以下的範例是計算三次多項式的值,輸入的參數有多個係數和 x 本身:
def cubic_poly_val(a, b, c, d, x): return a * x ** 3 + b * x * x + c * x + d print("When x = 1, 2x^3 + 3x^2 + 4x + 5 is", cubic_poly_val(2, 3, 4, 5, 1) ) print("When x = 5, 4x^3 + 3x^2 + 2x + 1 is", cubic_poly_val(4, 3, 2, 1, 5) )當然,也可以回傳多個結果,中間也是用逗點隔開。以下範例,是回傳一個二次式的值和它在該點的微分:
def quad_and_diff(a, b, c, x): y = a * x * x + b * x + c dy = 2 * a * x + b return y, dy y, dy = quad_and_diff(1, 2, 3, 4) print(y, dy) y, dy = quad_and_diff(5, 6, 7, 8) print(y, dy)函式當中可以呼叫其他的自訂函式或內建函式,以下是把多項式計算範例中的 x3 和 x2 的計算,分別改為呼叫自訂函式和內建函式來計算:
import math def x_cubic(x): return x * x * x def cubic_poly_val(a, b, c, d, x): return a * x_cubic(x) + b * math.pow(x, 2) + c * x + d print("When x = 1, 2x^3 + 3x^2 + 4x + 5 is", cubic_poly_val(2, 3, 4, 5, 1) ) print("When x = 5, 4x^3 + 3x^2 + 2x + 1 is", cubic_poly_val(4, 3, 2, 1, 5) )我們在開頭提到,透過函式可以將程式碼中常用的功能包裝起來。如果你的包裝不完善的話,很可能會造成該函式在使用上的困擾。以前面的多項式計算範例來說,如果你把 x3 和 x2 的計算放在沒有縮排的外部,則這個函式會難以被重複使用:
x = 1 x3 = x ** 3 x2 = x * x def cubic_poly_val(a, b, c, d, x): return a * x3 + b * x2 + c * x + d print("When x = 1, 2x^3 + 3x^2 + 4x + 5 is", cubic_poly_val(2, 3, 4, 5, 1) ) print("When x = 5, 4x^3 + 3x^2 + 2x + 1 is", cubic_poly_val(4, 3, 2, 1, 5) )一般來說,除非你很清楚自己有特別的設計需求,否則函式在計算時,請只依賴輸入的參數來進行。
日常生活中,你到飲料店買飲料,如果不指定甜度冰塊,或者是到拉麵店不要求調整湯頭鹹度和麵的軟硬度,店家可能會用一個預設的份量或程度來幫你製作飲料或拉麵。在程式中,我們也可以透過「預設參數」,來讓函式有預設行為。以下範例也會把把兩個數字相加,但是只給一個數字的時候,會把那個數字 +1:
def my_add(x, y=1): return x + y a = 3 b = 5 c = my_add(a) print(c) c = my_add(a, b) print(c)請留意,預設參數必須放在一般參數的後面,否則 Python 無從知道如何跟呼叫的方式對應。
函式當中的預設參數,在每次呼叫時都會重新給值:
def my_add(a=1): print("Value of a when entering my_add", a) a = a + 1 print("Value of a when exiting my_add", a) my_add() my_add() my_add()在一個函式中定義的變數,並無法從其他地方被讀取,這個稱為變數的範圍(scope)。以下範例中,test 函式裡外的變數 a 並不會互相干擾:
def my_add(a): a = a + 1 print('a in my_add:', a) a = 3 print('a outside:', a) my_add(a) print('a outside:', a)如果想在函式當中確實需要取用外部的變數(全域變數),比較妥善的做法是使用 global 關鍵字:
def my_add(a): global b a = a + 1 b = b + 1 print('a, b in my_add:', a, b) a = 3 b = 4 print('a, b outside:', a, b) my_add(a) print('a, b outside:', a, b)在 Python 當中,函式是「第一類物件(First-Class Object)」,可以被指派給變數後呼叫:
def my_add(x): return x + 1 a = 3 b = my_add a = b(a) print("New a:", a)