軌道
/
Python
Python
/
課程大綱
/
函式引數
函式

函式引數 在 Python

{other: "%{count} 個練習"}

關於 函式引數

關於函式引數的基礎知識,請參閱函式概念。

參數名稱

參數名稱和變數名稱一樣,必須以字母或底線開頭,並且可以包含字母、底線或數字。 參數名稱不應包含空格或標點符號。

位置引數

位置引數是依照參數綁定的順序傳入函式的值。 位置引數也可以選擇使用參數名稱來傳入:

def concat(greeting, name):
    return f"{greeting}{name}"

# Passing data to the function by position.
print(concat("Hello, ", "Lilly"))
#->  Hello, Lilly

# Passing data to the function using the parameter name.
print(concat(name="Glenn", greeting="Hello, "))
#-> Hello, Glenn

第一次呼叫concat時,是依照位置傳入引數。 第二次呼叫concat時,則是使用名稱傳入引數,因此可以改變它們的位置。

請注意,位置引數不能接在使用名稱傳入的引數後面(也稱為關鍵字引數。不要和可變位置參數或 **kwargs 搞混)。

像這組引數:

print(concat(greeting="Hello, ", "Gregor"))

會產生這個錯誤:

SyntaxError: positional argument follows keyword argument

若要求呼叫函式時只能使用僅限位置引數,可以透過在參數清單中使用/運算子來達成:

# Parameters showing a position-only operator. 
def concat(greeting, name, /):
    return f"{greeting}{name}"

print(concat("Hello, ", "Ginnie"))
#-> Hello, Ginnie

# Call to the function using keyword arguments.
print(concat(name="Franklin", greeting="Hello, "))
Traceback (most recent call last):
    print(concat(name="Franklin", greeting="Hello, "))
TypeError: concat() got some positional-only arguments passed as keyword arguments: 'greeting, name'

關鍵字引數

關鍵字引數是在呼叫函式時使用參數名稱。 它們也可以選擇依照位置來傳入:

def concat(greeting, name):
    return f"{greeting}{name}"

# Function call using parameter names as argument keywords.
print(concat(name="Eliza", greeting="Hello, "))
#-> Hello, Eliza

# Function call with positional data as arguments.
print(concat("Hello, ", "Tim"))
#-> Hello, Tim

若要求呼叫函式時只能使用僅限關鍵字引數,可以透過在參數清單中使用*運算子來達成:

# Function definition requiring keyword-only arguments.
def concat(*, greeting, name):
    return f"{greeting}{name}"

# Keyword arguments can be in an arbitrary order.
print(concat(name="Kimmie", greeting="Hello, "))
#-> Hello, Kimmie

# Calling the function with positional data raises an error.
print(concat("Hello, ", "Coleen"))
Traceback (most recent call last):
    print(concat("Hello, ", "Coleen"))
TypeError: concat() takes 0 positional arguments but 2 were given

預設引數值

可以在參數清單中為一個或多個引數提供預設值。 這樣一來,需要時就能用_更少_的引數來呼叫函式。 只要在呼叫函式時傳入新的引數值,就能覆寫預設值:

# Function with default argument values.
def concat(greeting, name="you", punctuation="!"):
    return f"{greeting}, {name}{punctuation}"

print(concat("Hello"))
#-> Hello, you!

# Overriding the default values
print(concat("Hello", name="Polly", punctuation="."))
#-> Hello, Polly.

位置或關鍵字引數

如果參數定義中沒有使用/或*運算子,引數就既可以依照位置、也可以使用關鍵字傳入。 或者,也可以把位置或關鍵字引數放在左邊的僅限位置參數,以及右邊的僅限關鍵字參數之間:

# Position-only argument followed by position-or-keyword, followed by keyword-only.
def concat(greeting, /, name, *, ending):
    return f"{greeting}{name}{ending}"

print(concat("Hello, ", "Mark", ending="!"))
#-> Hello, Mark!

print(concat("Hello, ", name="Rachel", ending="!"))
#-> Hello, Rachel!

print(concat(greeting="Hello, ", name="JoJo", ending="!"))
Traceback (most recent call last):
    print(concat(greeting="Hello, ", name="JoJo", ending="!"))
TypeError: concat() got some positional-only arguments passed as keyword arguments: 'greeting'

*args

程式碼範例經常會出現像下面這樣的函式定義:

def my_function(*args, **kwargs):
    # code snipped

*args是由兩部分組成的名稱,代表內含不定數量個別位置引數的tuple,也稱為variadic argument。 args是賦予這組引數tuple的名稱,但也可以換成任何其他有效的 Python 名稱,例如my_args、arguments等。 *是用來把這群個別引數轉換成tuple的運算子。

Note

如果你曾經拆解過 tuple,可能會覺得*args裡的*令人困惑。 在_參數_定義中,*並不會拆解 tuple,而是把一個或多個位置引數轉換_成_ tuple。

我們說*運算子多載,因為它在不同情境下的行為不同。 例如,*可以用來做乘法、用來拆解,也用來定義任意數量的位置參數。

由於tuple可以被疊代,args可以傳給任何接受可疊代物件的函式。 雖然*args經常和**kwargs一起出現,但並不是非得如此:

def add(*args):
    # args is passed to the sum function, which iterates over it.
    return sum(args)

print(add(1, 2, 3))
#-> 6

如果*args接在一個或多個位置引數後面,*args就會是位置引數之後剩下的部分:

def add(first, *args):
    # first will be 1, leaving the values 2 and 3 in *args
    return first + sum(args)

print(add(1, 2, 3))
#-> 6

如果在*args之後定義了一個或多個預設引數,它們會和*args的值分開:


def add(first, *args, last=0):
    return first + sum(args) + last
 
print(add(1, 2, 3))
#-> 6

print(add(1, 2, 3, last=4))
#-> 10

# This uses the unpacking operator * to separate the list elements into positional arguments.
# It does not have the same behavior as the * (packing) in *args.
print(add(*[1, 2, 3]))
#-> 6

請注意,當引數本身已經放在iterable裡(例如tuple或list),在傳給接受任意數量個別引數的函式之前,必須先拆解。 這是透過*來完成的,也就是拆解運算子。

在這個情境下,*會把容器_拆解_成一個個元素,再由*args轉換成tuple。 如果只有位置引數,拆解的結果必須和已定義的正式參數數量相同。

如果不先拆解傳入add的 list,程式就會發生錯誤:

def add(first, *args, last=0):
    return first + sum(args) + last

print(add([1, 2, 3]))
Traceback (most recent call last):
    print(add([1, 2, 3]))
    return first + sum(args) + last
TypeError: can only concatenate list (not "int") to list

**kwargs

**kwargs是由兩部分組成的名稱,代表不定數量個別的鍵值對引數。 kwargs是這群引數的名稱,也可以換成其他名稱,例如my_args、arguments等。 **會把這群具名引數轉換成由{argument name: argument value}配對組成的dictionary。

由於字典可以被疊代,kwargs可以傳給任何接受可疊代物件的函式。 雖然**kwargs經常和*args一起出現,但並不是非得如此:

def add(**kwargs):
    return sum(kwargs.values())

print(add(one=1, two=2, three=3))
#-> 6

請注意,這裡呼叫了dict.values()方法來逐一遍歷kwargs字典的values。 疊代字典時,預設是疊代_keys_,所以必須明確指定dict.values():

def concat(**kwargs):
    # Join concatenates the tuples from `kwargs.items()`
    return " ".join((str(item) for item in kwargs.items()))

print(concat(one=1, two=2, three=3))
#-> ('one', 1) ('two', 2) ('three', 3)
透過 GitHub 編輯 連結會在新視窗或分頁中開啟