3.5 傳遞任意數(shù)量的實(shí)參
當(dāng)不知道函數(shù)需要接受多少個(gè)實(shí)參時(shí),可以通過(guò)星號(hào)加一個(gè)空元組名來(lái)實(shí)現(xiàn)。
實(shí)例:一個(gè)制作比薩的函數(shù),它需要接受很多配料,但你無(wú)法預(yù)先確定顧客要多少種配料。
def make_pizza(*toppings):
? ? """概述要制作的比薩"""
? ? print("\nMaking a pizza with the following toppings:")
? ? for topping in toppings:
? ? ? ? print("- " + topping)
make_pizza('pepperoni') #一種原料
make_pizza('mushrooms', 'green peppers', 'extra cheese') #三種原料
3.5.1 結(jié)合使用位置實(shí)參和任意數(shù)量實(shí)參
如果要讓函數(shù)接受不同類(lèi)型的實(shí)參,必須在函數(shù)定義中將接納任意數(shù)量實(shí)參的形參放在最后。Python先匹配位置實(shí)參和關(guān)鍵字實(shí)參,再將余下的實(shí)參都收集到最后一個(gè)形參中。
示例:制作披薩餅函數(shù)中還需要一個(gè)表示比薩尺寸的實(shí)參,必須將該形參放在形參*toppings 的前面:
def make_pizza(size,*toppins):
? ? """概述要制作的比薩"""
? ? print("\nMaking a " + str(size) + "-inch pizza with the following toppings:")
? ? for toppin in toppins:
? ? ? ? print("- " + toppin)
make_pizza(16,'pepperoni')
make_pizza(22,'mushrooms', 'green peppers', 'extra cheese')
3.5.2 使用任意數(shù)量的關(guān)鍵字實(shí)參
有時(shí)候,需要接受任意數(shù)量的實(shí)參,但預(yù)先不知道傳遞給函數(shù)的會(huì)是什么樣的信息。在這種情況下,可在函數(shù)中傳入兩個(gè)星號(hào)加字典名的空字典參數(shù)。
實(shí)例:創(chuàng)建用戶(hù)簡(jiǎn)介,知道將收到有關(guān)用戶(hù)的信息,但不確定會(huì)是什么樣的信息。函數(shù)build_profile() 接受名和姓,同時(shí)還接受任意數(shù)量的關(guān)鍵字實(shí)參:
def build_profile(first, last, **user_info):
? ? """創(chuàng)建一個(gè)字典,其中包含我們知道的有關(guān)用戶(hù)的一切"""
? ? profile = {}
? ? profile['first_name'] = first
? ? profile['last_name'] = last
? ? for key, value in user_info.items():
? ? ? ? profile[key] = value? #往profile字典中添加新的鍵值
? ? return profile
user_profile = build_profile('albert', 'einstein',
? ? ? ? ? ? ? ? ? ? ? ? ? ? location='princeton',
? ? ? ? ? ? ? ? ? ? ? ? ? ? field='physics')
print(user_profile)
#執(zhí)行結(jié)果為{'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics'}
示例詳解:
? 函數(shù)build_profile() 的定義要求提供名和姓,同時(shí)允許用戶(hù)根據(jù)需要提供任意數(shù)量的名稱(chēng)—值對(duì)。形參**user_info 中的兩個(gè)星號(hào)讓Python創(chuàng)建一個(gè)名為user_info 的空字典,并將收到的所有名稱(chēng)—值對(duì)都封裝到這個(gè)字典中。在這個(gè)函數(shù)中可以像訪問(wèn)其他字典那樣訪問(wèn)user_info 中的名稱(chēng)—值對(duì)。
? 在build_profile() 的函數(shù)體內(nèi),我們創(chuàng)建了一個(gè)名為profile 的空字典,用于存儲(chǔ)用戶(hù)簡(jiǎn)介。先將肯定能收到的名和姓加入到這個(gè)字典中,然后遍歷字典user_info 中的鍵—值對(duì),并將每個(gè)鍵—值對(duì)都加入到字典profile 中。
? 將字典profile 返回給函數(shù)調(diào)用行。返回的字典中包含用戶(hù)的名和姓,還有求學(xué)的地方和所學(xué)專(zhuān)業(yè)。調(diào)用這個(gè)函數(shù)時(shí),不管額外提供了多少個(gè)鍵—值對(duì),它都能正確地處理。
? 我們調(diào)用build_profile() ,向它傳遞名('albert' )、姓('einstein' )和兩個(gè)鍵—值對(duì)(location='princeton' 和field='physics' ),并將返回的profile 存儲(chǔ)在變量user_profile 中,再打印這個(gè)變量。
3.6 將函數(shù)存儲(chǔ)在模塊中
函數(shù)的優(yōu)點(diǎn)之一是,使用它們可將代碼塊與主程序分離。通過(guò)給函數(shù)指定描述性名稱(chēng),可讓主程序容易理解得多。你還可以更進(jìn)一步,將函數(shù)存儲(chǔ)在被稱(chēng)為模塊的獨(dú)立文件中,再將模塊導(dǎo)入到主程序中。import 語(yǔ)句允許在當(dāng)前運(yùn)行的程序文件中使用模塊中的代碼。
通過(guò)將函數(shù)存儲(chǔ)在獨(dú)立的文件中,可隱藏程序代碼的細(xì)節(jié),將重點(diǎn)放在程序的高層邏輯上。這還能讓你在眾多不同的程序中重用函數(shù)。將函數(shù)存儲(chǔ)在獨(dú)立文件中后,可與其他程序員共享這些文件而不是整個(gè)程序。
3.6.1 導(dǎo)入整個(gè)模塊
模塊是擴(kuò)展名為.py的文件,包含要導(dǎo)入到程序中的代碼。
實(shí)例:
? 首先創(chuàng)建一個(gè)包含函數(shù)make_pizza() 的文件名稱(chēng)為pizza.py的模塊,內(nèi)容如下:
def make_pizza(size, *toppings):
? ? """概述要制作的比薩"""
? ? print("\nMaking a " + str(size) +
? ? ? ? ? "-inch pizza with the following toppings:")
? ? for topping in toppings:
? ? ? ? print("- " + topping)
? 然后在相同目錄其他文件中導(dǎo)入剛創(chuàng)建的模塊,并調(diào)用導(dǎo)入模塊中的函數(shù)make_pizza()。
import pizza
pizza.make_pizza(16, 'pepperoni') #調(diào)用方法:模塊名稱(chēng)+句點(diǎn)+函數(shù)名稱(chēng)
pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
上述導(dǎo)入整個(gè)模塊的方式,可使用指定導(dǎo)入的模塊的名稱(chēng)+句點(diǎn)+函數(shù)名即可調(diào)用模塊中所有函數(shù)。
3.6.2 導(dǎo)入特定的函數(shù)
可導(dǎo)入模塊中的特定函數(shù),這種導(dǎo)入方法的語(yǔ)法如下:
from module_name import function_name,如:
from pizza import make_pizza
通過(guò)用逗號(hào)分隔函數(shù)名,可根據(jù)需要從模塊中導(dǎo)入任意數(shù)量的函數(shù):
from module_name import function_0, function_1, function_2
3.6.3 使用as 給函數(shù)指定別名
如果要導(dǎo)入的函數(shù)的名稱(chēng)可能與程序中現(xiàn)有的名稱(chēng)沖突,或者函數(shù)的名稱(chēng)太長(zhǎng),可指定別名---函數(shù)的另一個(gè)名稱(chēng)。示例:
#函數(shù)make_pizza別名為mp
from pizza import make_pizza as mp
mp(16, 'pepperoni')
mp(12, 'mushrooms', 'green peppers', 'extra cheese')
3.6.4 使用as 給模塊指定別名
還可以給模塊指定別名。通過(guò)給模塊指定簡(jiǎn)短的別名,增加程序的簡(jiǎn)潔性。如:
#模塊pizza別名為p
import pizza as p
p.make_pizza(16, 'pepperoni')
p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
3.6.5 導(dǎo)入模塊中的所有函數(shù)
使用星號(hào)運(yùn)算符可讓Python導(dǎo)入模塊中的所有函數(shù),如:
from pizza import *
pizza.make_pizza(16, 'pepperoni') #
make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')
說(shuō)明:
? import 語(yǔ)句中的星號(hào)讓Python將模塊pizza 中的每個(gè)函數(shù)都復(fù)制到這個(gè)程序文件中。注意:與導(dǎo)入整個(gè)模塊的語(yǔ)法是不同的。
? 由于導(dǎo)入了每個(gè)函數(shù),可通過(guò)名稱(chēng)來(lái)調(diào)用每個(gè)函數(shù),而無(wú)需使用句點(diǎn)表示法。
? 然而,使用并非自己編寫(xiě)的大型模塊時(shí),最好不要采用這種導(dǎo)入方法:如果模塊中有函數(shù)的名稱(chēng)與你的項(xiàng)目中使用的名稱(chēng)相同,可能導(dǎo)致意想不到的結(jié)果,最佳的做法是,要么只導(dǎo)入你需要使用的函數(shù),要么導(dǎo)入整個(gè)模塊并使用句點(diǎn)表示法。
3.7 函數(shù)編寫(xiě)指南
編寫(xiě)函數(shù)時(shí),需要牢記幾個(gè)細(xì)節(jié)。
? 應(yīng)給函數(shù)指定描述性名稱(chēng),且只在其中使用小寫(xiě)字母和下劃線。描述性名稱(chēng)可幫助你和別人明白代碼想要做什么。給模塊命名時(shí)也應(yīng)遵循上述約定。
? 每個(gè)函數(shù)都應(yīng)包含簡(jiǎn)要地闡述其功能的注釋?zhuān)撟⑨寫(xiě)?yīng)緊跟在函數(shù)定義后面,并采用文檔字符串格式。文檔良好的函數(shù)讓其他程序員只需閱讀文檔字符串中的描述就能夠使用它:他們完全可以相信代碼如描述的那樣運(yùn)行;只要知道函數(shù)的名稱(chēng)、需要的實(shí)參以及返回值的類(lèi)型,就能在自己的程序中使用它。
? 如果程序或模塊包含多個(gè)函數(shù),可使用兩個(gè)空行將相鄰的函數(shù)分開(kāi),這樣將更容易知道前一個(gè)函數(shù)在什么地方結(jié)束,下一個(gè)函數(shù)從什么地方開(kāi)始。
? 給形參指定默認(rèn)值時(shí),等號(hào)兩邊不要有空格,對(duì)于函數(shù)調(diào)用中的關(guān)鍵字實(shí)參,也應(yīng)遵循這種約定:
? def function_name(parameter_0, parameter_1='default value')
? function_name(value_0, parameter_1='value')
3.8 本章小結(jié)
? 在本章中,學(xué)習(xí)函數(shù)相關(guān)語(yǔ)法知識(shí):
? 如何編寫(xiě)函數(shù),以及如何傳遞實(shí)參,讓函數(shù)能夠訪問(wèn)完成其工作所需的信息;
? 如何使用位置實(shí)參和關(guān)鍵字實(shí)參,以及如何接受任意數(shù)量的實(shí)參;
? 顯示輸出的函數(shù)和返回值的函數(shù);
? 如何將函數(shù)同列表、字典、if 語(yǔ)句和while 循環(huán)結(jié)合起來(lái)使用。
? 如何將函數(shù)存儲(chǔ)在被稱(chēng)為模塊的獨(dú)立文件中,讓程序文件更簡(jiǎn)單、更易于理解。
? 學(xué)習(xí)了函數(shù)編寫(xiě)指南,遵循這些指南可讓程序始終結(jié)構(gòu)良好,并對(duì)你和其他人來(lái)說(shuō)易于閱讀。
? 在本章中,學(xué)習(xí)函數(shù)的優(yōu)點(diǎn):
? 函數(shù)讓程序簡(jiǎn)潔,易于維護(hù)管理。編寫(xiě)代碼一次后,想重用它們多少次就重用多少次。需要修改函數(shù)的行為時(shí),只需修改一個(gè)代碼塊,而所做的修改將影響調(diào)用這個(gè)函數(shù)的每個(gè)地方。
? 使用函數(shù)讓程序更容易閱讀,而良好的函數(shù)名概述了程序各個(gè)部分的作用。相對(duì)于閱讀一系列的代碼塊,閱讀一系列函數(shù)調(diào)用讓你能夠更快地明白程序的作用。
? 函數(shù)還讓代碼更容易測(cè)試和調(diào)試。如果程序使用一系列的函數(shù)來(lái)完成其任務(wù),而其中的每個(gè)函數(shù)都完成一項(xiàng)具體的工作,測(cè)試和維護(hù)起來(lái)將容易得多:
? 可編寫(xiě)分別調(diào)用每個(gè)函數(shù)的程序(測(cè)試用例),測(cè)試每個(gè)函數(shù)是否在它可能遇到的各種情形下都能正確地運(yùn)行。確保它們都將正確地運(yùn)行。