引數匹配順序——Python學習之引數(三)

ARM的程式設計師敲著詩歌的夢發表於2020-04-04

引數匹配順序——Python學習之引數(三)


這篇博文是對上一篇博文引數匹配模型的總結與擴充套件。

函式引數匹配表

下面的表格總結了Python中引數匹配的語法。
在這裡插入圖片描述

考慮到翻譯過來可能不準確,我就不翻譯成中文了。

引數匹配順序

函式呼叫中,引數必須以此順序出現:任何位置引數,後面跟著任何關鍵字引數(name=value)和*iterable形式的組合,最後是**dict形式。

函式頭部,引數必須以此順序出現:任何一般引數(name),緊跟著任何預設引數(name=value),再然後是*name,再再然後是 keyword-only 引數(name或者name=value),最後是**name形式。

注意:在函式呼叫和函式頭部中,如果出現**arg形式的話,都必須出現在最後

Python內部是按照以下的步驟在賦值前進行引數匹配的:

  1. 通過位置分配非關鍵字引數。
  2. 通過匹配變數名分配關鍵字引數。
  3. 其他額外的非關鍵字引數分配到*name元組中
  4. 其他額外的關鍵字引數分配到**name字典中。
  5. 用預設值分配給在頭部未得到分配的引數。

keyword-only 引數的位置

在一個函式頭部,keyword-only 引數必須編寫在**arg之前、*arg之後(如果二者都有的話)。無論何時,一個引數名稱出現在*arg之前,它應該是預設位置引數,而不是keyword-only 引數。

>>> def f(a, *b, **d, c=6): print(a, b, c, d)          # Keyword-only before **!
SyntaxError: invalid syntax
>>> def f(a, *b, c=6, **d): print(a, b, c, d)          
>>> f(1, 2, 3, x=4, y=5)                               # Default used
1 (2, 3) 6 {'y': 5, 'x': 4}
>>> f(1, 2, 3, x=4, y=5, c=7)                          # Override default
1 (2, 3) 7 {'y': 5, 'x': 4}

>>> f(1, 2, 3, c=7, x=4, y=5)                          # Anywhere in keywords
1 (2, 3) 7 {'y': 5, 'x': 4}

>>> def f(a, c=6, *b, **d): print(a, b, c, d)        # c is not keyword-only here!
>>> f(1, 2, 3, x=4)
1 (3,) 2 {'x': 4}

第1行的寫法是錯誤的,如果c是一個keyword-only 引數,那麼它必須在*b之後,**d之前,即第3行那樣。

第4行和第6行是函式呼叫,區別是第4行採用了引數c的預設值,第6行覆蓋了預設值。

第12行,c=6是一個帶有預設值的位置引數,第13行的“2”覆蓋了c的預設值。

在函式呼叫中,keyword-only 引數可以編寫在*arg之前或之後,也可能包含在**arg中。

第1行,c 是一個帶有預設值的keyword-only 引數。

>>> def f(a, *b, c=6, **d): print(a, b, c, d)          # KW-only between * and **
>>> f(1, *(2, 3), **dict(x=4, y=5))                    # Unpack args at call
1 (2, 3) 6 {'y': 5, 'x': 4}

>>> f(1, *(2, 3), **dict(x=4, y=5), c=7)               # Keywords before **args!
SyntaxError: invalid syntax
    
>>> f(1, *(2, 3), c=7, **dict(x=4, y=5))               # Override default
1 (2, 3) 7 {'y': 5, 'x': 4}

>>> f(1, c=7, *(2, 3), **dict(x=4, y=5))               # After or before *
1 (2, 3) 7 {'y': 5, 'x': 4}

>>> f(1, *(2, 3), **dict(x=4, y=5, c=7))               # Keyword-only in **
1 (2, 3) 7 {'y': 5, 'x': 4}

第5行,c=7 應該出現在 **dict(x=4, y=5) 之前;

第8和11行,c=7 可以出現在 *(2, 3)之後或之前;

第14行,c=7 可以出現在**dict(x=4, y=5, c=7)中。








【本系列完】

前兩篇文章分別是:
引數匹配模型——Python學習之引數(二)
Python學習之引數(一)


參考資料

《Python學習手冊(第4版)》,機械工業出版社

《Learning Python 5th Edition》, O’Reilly

相關文章