Python函數可變引數詳解

2020-07-16 10:05:02
在實際使用函數時,可能會遇到“不知道函數需要接受多少個實參”的情況,不過好在 Python 允許函數從呼叫語句中收集任意數量的實參。

例如,設計一個製作披薩的函數,我們知道,披薩中可以放置很多種配料,但無法預先確定顧客要多少種配料。該函數的實現方式如下:
def make_pizza(*toppings):
    """列印顧客點的所有配料"""
    print(toppings)
make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')
可以看到,make_pizza() 函數中,只包含一個形參 *toppings,它表示建立一個名為 toppings 的空元組,並將收到的所有值都封裝到這個元組中。並且,函數體內的 print() 通過生成輸出來證明 Python 既能夠處理使用一個值呼叫函數的情形,也能處理使用三個值來呼叫函數的情形。

因此,上面程式的輸出結果為:

('pepperoni',)
('mushrooms', 'green peppers', 'extra cheese')

函數接收任意數量的非關鍵字實參

注意,如果函數引數中既要接收已知數量的實參,又要接收任意數量的實參,則必須遵循一個原則,即將接納任意數量實參的形參放在最後。

這種情況下,Python 會先匹配位置實參,再將餘下的實參收集到最後一個形參中。

仍以製作披薩為例,現在需要客人明確指明要購買披薩的尺寸,那麼修改後的函數如下所示:
def make_pizza(size, *toppings):
    """概述要製作的披薩"""
    print("nMaking a " + str(size) + "-inch pizza with the following toppings:")
    for topping in toppings:
        print("- " + topping)
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
輸出結果為:

Making a 16-inch pizza with the following toppings:
- pepperoni

Making a 12-inch pizza with the following toppings:
- mushrooms
- green peppers
- extra cheese

可以看到,Python 將收到的第一個值儲存在形參 size 中,並將其他的所有值都儲存在元組 toppings 中。

函數接收任意數量的關鍵字實參

如果在呼叫函數時是以關鍵字引數的形式傳入實參,且數量未知,則需要使函數能夠接收任意數量的鍵值對引數。

舉個例子:
def build_profile(first, last, **user_info):
    profile = {}
    profile['first_name'] = first
    profile['last_name'] = last
    for key, value in user_info.items():
        profile[key] = value
    return profile
user_profile = build_profile('albert', 'einstein', location='princeton', field='physics')
print(user_profile)
執行結果為:

{'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics'}

注意觀察,函數 build_profile() 中,形參 **user_info 表示建立一個名為 user_info 的空字典,並將接受到的所有鍵值對都儲存到這個字典中。

這裡的 **user_info 和普通字典一樣,我們可以使用存取其他字典那樣存取它儲存的鍵值對。


以上分別給大家介紹了如何實現讓函數接收任意個(普通方式傳遞的)實參以及任意個關鍵字實參。其實,在實際程式設計中,這兩種方式可以結合使用。例如:
def build_profile(first, last, *infos, **user_info):
    print(first,last)
    for info in infos:
        print(info)
    for key, value in user_info.items():
        print(key,":",value)

build_profile('first:albert', 'last:einstein', "age:29","TEL:123456",location='princeton', field='physics')
執行結果為:

first:albert last:einstein
age:29
TEL:123456
location : princeton
field : physics