---
# System prepended metadata

title: Argue of Arguments and Keyword-arguments
tags: [Python]

---

# Argue of Arguments and Keyword-arguments

整理一下 Python 中的技巧：`*args` 和 `**kwargs`。

`*args` 是處理「函數中不定數量的位置引數」，而 `**kwargs` 是處理「關鍵字引數」的語法。因為還不太熟悉這些語法，於是就想寫這篇來釐清一下。要注意的是沒有 `*kwargs` ，因為 `*kwargs` 就是 `*args`。

### About Parameter and Argument

- 定義函數叫做引數（Parameter）
- 傳遞函數叫做參數（Argument）

# `*args`

首先我們先來介紹當用在引數時的 `*args`

### Example

```python
def func(*arg1, arg2):
    print(arg1, arg2)

func(1, 2, 3, 4, 5, arg2=300)
```

```shell
$ python3 main.py
(1, 2, 3, 4, 5) 300
```

在這裡我們可以看到呼叫 `func()` 時帶入的參數為一串整數，一直到最後一個 `arg2` 時才完整打上 `arg2=300` 告訴函數位於 `arg2` 的參數為多少，這個寫法能讓 Python 正確解析跑出數值，所以此程式是沒有錯誤的。

### Summary

使用者在輸入 `*args` 引數時，能於該參數傳遞不只一項數值。當某情況需要傳遞多數值時就可以用 `*args` 來打包一狗票東西到一個 Tuple 裡，而不用預先將資料打包在容器裡後傳入。當使用者輸入完 `*args` 欄位時，則需要特別打上下一個參數名稱來提醒直譯器 `*args` 欄位輸入完畢。

總結一下，上面程式中我到底輸入了什麼、函數拿到了什麼？
我們可以改寫一下程式：

```python
def func(*arg1, arg2):
    print(arg1)
    print(arg2)

func(1, 2, 3, 4, 5, arg2=300)
```

```shell
$ python3 main.py
(1, 2, 3, 4, 5)
300
```

就能知道 `(1, 2, 3, 4, 5)` 為 `*arg1` 的引數、`300` 為 `arg2` 的引數。

# `**kwargs`

Python 中有 Keyword 用法的結構只有 Dictionary，那在這邊的 `**kwargs` 是以 Key-Value pair 的結構出現。但這裡的用法稍微特殊，當使用 `**kwargs` 時，傳遞的引數會是 Variable-Value pair。

### Example

```python
def func(**kwargs):
    print(kwargs)

func(a=1, b=2, c=3, d=4)
```

```shell
$ python3 main.py
{'a': 1, 'b': 2, 'c': 3, 'd': 4}
```

### Summary

也就是像上面範例一樣，傳遞的是一組一組的 Variable 與 Value。這種就是 `**kwargs` 的基本用法。再來我們可以看到，經過 `**kwargs` 後的 Variable-Value paie 被轉換成了 Key-Value pair，也就是說，透過傳遞給 `**kwargs` 後我們會得到一個字典回傳值。

# `*args` and `**kwargs`

從前面認識了 `*args` 與 `**kwargs`，也發現到 `**kwargs` 有包裝的特性外，也具備 `*args` 傳遞多筆參數的性質。所以現在想知道如何同時使用 `*args` 和 `**kwargs` 。
 
其實很簡單，只要將 `*args` 與 `**kwargs` 的兩個性質放在一起就可以了。最終，在呼叫函數時的引數會是這樣：

### Example

```python
def func(*args, **kwargs):
    print(args)
    print(kwargs)
    
func(1, 2, 3, a=1, b=2, c=3)
```

```shell
$ python3 main.py
(1, 2, 3)
{'a': 1, 'b': 2, 'c': 3}
```

### Summary

當同時使用 `*args` 與 `**kwargs` 時，只需要把在 `*args` 段落中其他的參數全部想像成 `**kwargs`。只要依照這個思路去記，就能無痛將 `*args` 與 `**kwargs` 全部記下來！

# `*args` and `*args` or `**kwargs` and `**kwargs`

直譯器會報錯 `SyntaxError: * argument may appear only once` 或 `SyntaxError: arguments cannot follow var-keyword argument`。

# Reference

- [Glossary - Python 3.11.0 documentation](https://docs.python.org/3/glossary.html#term-parameter)
