2.15. 引數¶
函式可以用數種方式呼叫,其參數也可以用數種形態宣告。這些組合乍看之下令人卻步;但實務上三、四種模式幾乎涵蓋了一切。
2.15.1. 位置引數與關鍵字引數¶
最簡單的呼叫是按 位置 傳遞引數 -- 第一個值給第一個參數,第二個值給第二個參數,依此類推:
def rect(x, y, w, h):
return (x, y, w, h)
rect(10, 20, 100, 50)
同樣的呼叫也可以按 關鍵字 傳遞引數,明確指名每個參數:
rect(x=10, y=20, w=100, h=50)
關鍵字引數與順序無關,並使呼叫具有自我說明性,代價是需要多打一些字。位置引數與關鍵字引數可以在單次呼叫中混用,但每個位置引數都必須出現在任何關鍵字引數之前:
rect(10, 20, w=100, h=50) # OK
rect(x=10, 20, 100, 50) # SyntaxError
2.15.2. 預設值¶
參數可以宣告一個預設值,以在呼叫者未提供時使用:
def greet(name, greeting="hello"):
print(greeting, name)
greet("Alice") # hello Alice
greet("Alice", "hi") # hi Alice
greet("Alice", greeting="hey") # hey Alice
在 def 行中,具有預設值的參數必須位於沒有預設值的參數 之後。
警告
預設值只會在 def 執行時評估一次 -- 而非每次呼叫時。使用可變的預設值([]、{})會導致 同一個 物件在每次採用該預設值的呼叫之間共用。請改用 None 作為哨兵值:
def append_to(item, target=None):
if target is None:
target = []
target.append(item)
return target
2.15.3. 可變長度:*args 與 **kwargs¶
以 * 為前綴的參數會將任何剩餘的位置引數收集進一個 tuple。以 ** 為前綴的參數會將任何剩餘的關鍵字引數收集進一個 dict。慣用的名稱是 args 與 kwargs,但任何識別字都可以:
def report(label, *values, **options):
print(label, values, options)
report("temps", 21, 22, 23, unit="C", precision=1)
輸出::
temps (21, 22, 23) {'unit': 'C', 'precision': 1}
函式很少需要兩者同時使用。最常見的用途是將引數從包裝函式轉發給內層呼叫:
def log_and_call(func, *args, **kwargs):
print("calling", func.__name__)
return func(*args, **kwargs)
在 呼叫 端的鏡像語法則會將一個可迭代物件解包成位置引數(*),或將一個 dict 解包成關鍵字引數(**):
point = (10, 20, 100, 50)
rect(*point) # same as rect(10, 20, 100, 50)
kwargs = {"x": 10, "y": 20, "w": 100, "h": 50}
rect(**kwargs) # same as rect(x=10, y=20, ...)
2.15.4. 僅限關鍵字的參數¶
在參數列表中單獨出現的 *(不附加在名稱上)會將其後的每個參數標記為 僅限關鍵字 -- 呼叫者必須使用名稱:
def crop(buffer, *, x, y, w, h):
...
crop(buffer, x=0, y=0, w=100, h=100) # OK
crop(buffer, 0, 0, 100, 100) # TypeError
對於布林旗標以及其他在呼叫端若僅有裸值便無法自我說明的引數,請使用這種方式。