1. 引言

Python 作為一種動態類型語言(Dynamically Typed Language),提供了高度靈活的函數形式參數(Formal Parameters)定義方式。不同於許多靜態類型語言對函數參數數量與類型的嚴格約束,Python 允許函數在運行時接受不定數量的參數,並基於內部模型自動完成參數綁定(Argument Binding)。

其中,*args**kwargs 是 Python 函數參數體系的核心特性,用於處理變長參數與構建開放式、可擴展的函數接口。它們在標準庫設計(如 print()loggingmatplotlib)與各類框架(如 Django、Flask、FastAPI)中被廣泛使用。

2. 語法機制

  1. *args:可變位置參數(Variable Positional Arguments)
    帶有前綴 * 的形式參數用於捕獲調用時傳入的所有 額外位置實參(positional arguments)
    語法格式如下:
def function_name(*args):
    pass
  • args 接收一個 tuple 類型對象。
  • 參數名稱可以自定義,但根據 PEP 8 規範一般使用 args

示例:

def f(*args):
    print(args)

f(10, 20, 30)
# 輸出: (10, 20, 30)
  1. **kwargs:可變關鍵字參數(Variable Keyword Arguments)
    帶有前綴 ** 的形式參數用於捕獲所有未被其它具名參數綁定的 額外關鍵字實參(keyword arguments)
def function_name(**kwargs):
    pass
  • kwargs 接收一個 dict[str, Any] 對象。
  • 字典鍵必須為字符串,這是 Python 語法層面保證的約束。

示例:

def f(**kwargs):
    print(kwargs)

f(a=1, b=2)
# 輸出: {'a': 1, 'b': 2}
  1. 參數定義順序(Parameter Ordering Rules)
    根據 Python 語法規範(參考 PEP 3102),函數參數必須遵循以下順序:
def func(
    positional_parameters,
    default_parameters,
    *args,
    keyword_only_parameters,
    **kwargs
):
    ...

錯誤順序將導致解析階段報錯。

3. 類型特徵

  1. *args 的類型語義
    *args 的內部類型始終為:
tuple[Any, ...]

無論傳入多少實參均滿足此結構。

  1. **kwargs 的類型語義
    **kwargs 的類型固定為:
dict[str, Any]

其中:

  • 鍵(key)類型必須為 str(由語法生成)。
  • 值(value)類型不受限制。
  1. 類型提示(Type Hinting)規範
    基於 PEP 484 與 PEP 612,官方推薦的註解方式如下:
def func(*args: int, **kwargs: str) -> None:
    ...

其語義為:

  • args 是 “tuple of int”
  • kwargs 是 “dict[str, str]”

進一步形式化表示:

args: tuple[int, ...]
kwargs: dict[str, str]

4. 運行機制與內部模型

  1. 參數打包(Packing)過程
    在調用函數時,例如:
func(1, 2, 3, x=10, y=20)

Python 的內部參數綁定流程可概括為:

  1. 位置參數依次與具名位置形參綁定。
  2. 多餘的位置參數被收集並構成一個 tuple,綁定給 *args
  3. 關鍵字參數與具名關鍵字形參匹配。
  4. 多餘的關鍵字參數構成一個 dict,綁定給 **kwargs
  1. 參數解包(Unpacking)過程
    使用 *** 可在調用時進行解包:
data = (1, 2)
options = {"x": 10}

func(*data, **options)

內部等價於:

func(1, 2, x=10)

這為 Python 設計動態 API 提供關鍵能力。

5. 設計初衷

  1. 構建高度動態的函數接口
    Python 強調“鴨子類型”(Duck Typing)與運行時靈活性,因而需要允許函數接受:
  • 任意數量的位置參數
  • 任意數量的關鍵字參數

這對框架設計尤為重要,如:

  • Flask 的視圖函數
  • Django 的類視圖方法
  • Numpy 與 Pandas 的構造與操作函數

這些函數都無法預先預測用户將提供哪些參數。

  1. 代理與轉發
    構建代理函數或裝飾器時,必須保證參數不丟失:
def wrapper(*args, **kwargs):
    return target(*args, **kwargs)

這是裝飾器設計模式在 Python 中得以實現的基石。

  1. 保證繼承體系中的兼容性
    在面向對象繼承體系中,子類方法經常需要保持對父類接口的兼容性:
class Base:
    def run(self, *args, **kwargs):
        pass

子類可以擴展參數而不會破壞方法簽名。

  1. 構建可擴展的配置接口
    科學計算、繪圖庫等大量採用 **kwargs 作為可擴展配置入口,例如:
plt.plot(..., linewidth=2, label="test", color="red")

這是一種開放 API(Open API)的典型設計方式。

6. 使用注意事項

  1. 避免濫用
    不必要地使用 *args**kwargs 可能損害可讀性,建議僅在需要提供擴展性或構建框架級 API 時使用。
  2. args 是不可變 tuple
    如需調整其內容需顯式轉換:
args = list(args)
  1. 關鍵字參數鍵必須是字符串
    以下寫法為非法:
func(**{1: "invalid"})  # SyntaxError
  1. 注意函數簽名的清晰可讀性
    在庫開發中,建議保留基礎參數並將可擴展部分交由 **kwargs 處理:
def connect(host: str, port: int, **options: Any) -> None:
    ...

7. 總結

*args**kwargs 是 Python 函數機制中最具動態性與擴展能力的元素,它們構成了:

  1. Python 高度靈活的參數調用模型
  2. 框架與庫設計的通用接口機制
  3. 裝飾器與代理模式的基礎設施

通過理解其語法、類型結構與底層動因,開發者可以更有效地構建兼具簡潔性與可擴展性的函數接口,從而充分發揮 Python 動態語言的優勢。