控制流程 <<
Previous Next >> 複製與參照
簽章
簽章
函式 (Function) 能在特定需求時輸入資料與輸出結果,輸入與輸出值稱為參數 (Argument)。
以強型別程式語言 C 來說,一個輸入 3 個參數,輸出 1 個參數的函式是這樣宣告的:
int func(int p0, int p1, float p2);
但是 Python 沒有類型標示,因此函式會如此定義:
def func(p0, p1, p2):
...
函式 func 的輸入與輸出類型(如「輸入 3 個參數、輸出 1 個參數」),稱為簽章 (Signature)。
Python 是弱型別語言,簽章只有強制規定參數數量,而沒有規定參數類型。
另外,單一化的輸入需求不足以滿足函式應用範圍,而產生多載 (Overload) 的功能,以支援不同選項、不同類型的輸入。以強型別程式語言 C++ 為例:
// 注意:C 語言不支援多載。
// C++ 多載宣告,編譯時會依照簽章自動生成四種函式。
// 預設值也算是一種多載。
// 撰寫程式時只需要寫 func 即可。
int func(int p0, int p1, long double p2, bool p3 = false);
int func(int p0, int p1, double p2) {
// 會需要寫轉換型別的接繞函式。
// 如果簽章搞錯,會造成無限遞迴 (Recursive)。
return func(p0, p1, (long double) p2);
}
int func(int p0, int p1, float p2) {
// 會需要調整設定。
return func(p0, p1, (long double) p2, true);
}
上面的例子中,為了支援強型別的標記,函式必須製作多種不同類型的簽章,若有更多需求,則必須使用模板 (Template):
// 模板宣告,編譯時會自動生成多載簽章。
template <typename T>
int func(int p0, int p1, T p2);
// 如果要支援其他參數,又要混合多載。
int func(int p0, int p1, long double p2, bool p3 = false);
在 Python 中,沒有多載、沒有模板、沒有型別要求,因此大幅簡化定義。唯一要解決的問題是滿足參數數量的變化。
預設值
預設值只能從最後開始使用等於 = 符號連續定義,不可以隨意指定其中的參數。
在呼叫時使用 = 符號為關鍵字參數,與定義時相同,只能從最後開始連續填入。
def func(p0, p1, p2=20, p3=True):
...
# 可以這樣使用:
func(a0, a1, a2, a3) # 全部填滿。
func(a0, a1, a2) # 使用部分預設值。
func(a0, a1, p3=a3) # 名稱對應,使用部分預設值。
func(a0, a1) # 全部使用預設值。
強制名稱對應
使用特殊符號 *,其後所有參數不分順序,強制使用名稱對應。如果有參數沒有填入或沒有預設值,會引發錯誤。
def func(p0, p1, *, p2, p3=True):
...
# 可以這樣使用:
func(a0, a1, p2=a2, p3=a3) # 全部填滿。
func(a0, a1, p2=a2) # 名稱對應,全部使用預設值。
順序收集與對應收集
使用星號 *,該變數會收集多餘填入的位置參數 (Positional argument)。多餘的參數會收集成 tuple 容器,若沒有多餘參數,該參數會是空的 tuple 容器。
使用雙星號 **,該變數會收集多餘填入的關鍵字參數 (Keyword argument)。多餘的參數會收集成 dict 容器,若沒有多餘參數,該參數會是空的 dict 容器。
兩者可以擇一或混合使用,但是定義時單星號參數一定要在前面,其後所有參數不分順序。
def func(p0, p1, *p2, **p3, p4, p5=True):
...
# 可以這樣使用:
func(a0, a1, p4=a4, p5=a5) # 全部填滿。
# p2 = ()
# p3 = {}
func(a0, a1, p4=a4) # 全部使用預設值。
# p2 = ()
# p3 = {}
func(a0, a1, b1, b2, r=b3, s=b4, p4=a3) # 多餘值。
# p2 = (b1, b2)
# p3 = {'r': b3, 's': b4}
針對「順序容器(如 tuple、list)」或「成對容器(如 dict)」,填入時可以用 *、** 按關係填入。不過不符合簽章仍然會引發錯誤,應當注意。如:
func(*[a0, a1, b1, b2], **{'r':b3, 's': b4, 'p4': a3})
# 或用變數:
a_list = [a1, b1, b2]
b_dict = {'r':b3, 'p4': a3}
func(a0, s=b4, *a_list, **b_dict)
控制流程 <<
Previous Next >> 複製與參照