使用任意數量的引數定義函式

任意數量的位置引數:

定義一個能夠獲取任意數量引數的函式可以通過在其中一個引數前加一個*來完成

def func(*args):
    # args will be a tuple containing all values that are passed in
    for i in args:
        print(i)

func(1, 2, 3)  # Calling it with 3 arguments
# Out: 1
#      2
#      3

list_of_arg_values = [1, 2, 3]
func(*list_of_arg_values)  # Calling it with list of values, * expands the list
# Out: 1
#      2
#      3 

func()  # Calling it without arguments
# No Output 

不能args 提供預設值,例如 func(*args=[1, 2, 3]) 會引發語法錯誤(甚至不會編譯)。

呼叫函式時,你不能通過名稱提供這些,例如 func(*args=[1, 2, 3]) 將引發 TypeError

但是如果你已經在一個陣列(或任何其他 Iterable)中有你的引數,你可以像這樣呼叫你的函式:func(*my_stuff)

這些引數(*args)可以通過索引訪問,例如 args[0] 將返回第一個引數

任意數量的關鍵字引數

你可以通過在定義中定義一個帶有兩個 * 的引數來獲取具有名稱的任意數量的引數 :

def func(**kwargs):
    # kwargs will be a dictionary containing the names as keys and the values as values
    for name, value in kwargs.items():
        print(name, value)

func(value1=1, value2=2, value3=3)   # Calling it with 3 arguments
# Out: value1 1
#      value2 2
#      value3 3

func()                               # Calling it without arguments
# No Out put

my_dict = {'foo': 1, 'bar': 2}
func(**my_dict)                      # Calling it with a dictionary
# Out: foo 1
#      bar 2

不能提供這些沒有名字,例如 func(1, 2, 3) 將提出一個 TypeError

kwargs 是一個普通的本地 python 字典。例如,args['value1'] 將給出引數 value1 的值。務必事先檢查是否存在這樣的爭論或者提出了一個 KeyError

警告

你可以將這些與其他可選引數和必需引數混合,但定義中的順序很重要。

位置/關鍵字引數是第一位的。 (必需的引數)。
然後是任意的 *arg 引數。 (可選的)。
接下來是關鍵字引數。 (需要)。
最後任意關鍵字 **kwargs 來了。 (可選的)。

#       |-positional-|-optional-|---keyword-only--|-optional-|
def func(arg1, arg2=10 , *args, kwarg1, kwarg2=2, **kwargs):
     pass
  • 必須提供 arg1,否則提出 TypeError。它可以作為位置(func(10))或關鍵字引數(func(arg1=10))給出。
  • kwarg1 也必須給出,但它只能作為 keyword-argument 提供:func(kwarg1=10)
  • arg2kwarg2 是可選的。如果要更改該值,則應用與 arg1(位置或關鍵字)和 kwarg1(僅關鍵字)相同的規則。
  • *args 捕獲額外的位置引數。但請注意,arg1arg2 必須作為位置引數提供,以便將引數傳遞給*argsfunc(1, 1, 1, 1)
  • **kwargs 捕獲所有其他關鍵字引數。在這種情況下,任何引數不是 arg1arg2kwarg1kwarg2。例如:func(kwarg3=10)
  • 在 Python 3 中,你可以單獨使用*來指示必須將所有後續引數指定為關鍵字。例如,Python 3.5 及更高版本中的 math.isclose 函式是使用 def math.isclose (a, b, *, rel_tol=1e-09, abs_tol=0.0) 定義的,這意味著前兩個引數可以在位置提供,但可選的第三和第四個引數只能作為關鍵字引數提供。

Python 2.x 不支援僅關鍵字引數。可以使用 kwargs 模擬此行為:

def func(arg1, arg2=10, **kwargs):
    try:
        kwarg1 = kwargs.pop("kwarg1")
    except KeyError:
        raise TypeError("missing required keyword-only argument: 'kwarg1'")

    kwarg2 = kwargs.pop("kwarg2", 2)
    # function body ...

關於命名的注意事項

命名可選位置引數 args 和可選關鍵字引數 kwargs 的約定只是一個約定,你可以使用你喜歡的任何名稱,遵循約定是有用的,以便其他人知道你在做什麼,甚至你自己以後所以請這樣做。

關於唯一性的註釋

任何函式都可以定義為沒有或一個 *argsnone 或一個 **kwargs 但不能多於一個。*args必須是最後一個位置引數,**kwargs 必須是最後一個引數。嘗試使用多箇中的任何一個都導致語法錯誤異常。

關於使用可選引數巢狀函式的注意事項

可以巢狀這樣的函式,通常的慣例是刪除程式碼已經處理過的專案但是如果要傳遞引數,則需要傳遞帶有*字首的可選位置引數和帶有**字首的可選關鍵字 args,否則 args 將作為列表或元組和 kwargs 作為單個字典傳遞。例如:

def fn(**kwargs):
    print(kwargs)
    f1(**kwargs)

def f1(**kwargs):
    print(len(kwargs))

fn(a=1, b=2)
# Out:
# {'a': 1, 'b': 2}
# 2