0%

將*當作函式參數來強制使用關鍵字引數

很特別的可以直接當作一個函式的參數來使用。如果當作函式的參數,可以用來限定*之後不可以使用位置引數,但可以使用關鍵字引數,這樣的使用方法被稱為Keyword-Only Arguments

以下以位置引數(Positional Argument)與關鍵字引數(Keyword Argument)中的計算小考平均成績為例說明:

1
2
def total_score(eng_score, math_score, eng_weight=0.5, math_weight=0.5):    
return eng_scoreeng_weight + math_scoremath_weight

在這個範例中,可以使用以下4種方式來呼叫函式都是沒問題的

1
2
3
4
5
6
7
8
>>> total_score(80, 90)  # 省略且不指定有預設值的參數
85
>>> total_score(eng_score=80, eng_weight=0.2, math_score=90, math_weight=0.8) # 使用關鍵字引數,可隨意安排順序
88
>>> total_score(80, 90, math_weight=0.8, eng_weight=0.2) # 混用位置和關鍵字引數
88
>>> total_score(80, 90, 0.2, 0.8) # 單純使用位置引數
88

但如果今天在原本的函式中,把*加入到第三個參數,這樣在第四種單純使用位置引數來作函式呼叫就會引發TypeError,因為在之後不能使用位置引數

1
2
3
4
5
def total_score(eng_score, math_score, * , eng_weight=0.5, math_weight=0.5):    
return eng_scoreeng_weight + math_score*math_weight

>>> total_score(80, 90, 0.2, 0.8) # 單純使用位置引數
TypeError: total_score() takes 2 positional arguments but 4 were given

今天如果要設計成防止呼叫者使用任何位置引數,就可以將*做為第一個參數,這樣就可以強迫叫者全部使用關鍵字引數,若使用任何的位置引數,都會引發TypeError

1
2
3
4
5
6
7
8
9
10
11
def total_score(*, eng_score, math_score, eng_weight=0.5, math_weight=0.5):    
return eng_scoreeng_weight + math_score*math_weight

>>> total_score(80, 90) # 省略且不指定有預設值的參數
TypeError: total_score() takes 0 positional arguments but 2 were given

>>> total_score(80, 90, math_weight=0.8, eng_weight=0.2) # 混用位置和關鍵字引數
TypeError: total_score() takes 0 positional arguments but 2 positional arguments (and 2 keyword-only arguments) were given

>>> total_score(80, 90, 0.2, 0.8) # 單純使用位置引數
TypeError: total_score() takes 0 positional arguments but 4 were given

PEP 3102 – Keyword-Only Arguments