python函数的高级用法
傳遞列表
你經(jīng)常會發(fā)現(xiàn),向函數(shù)傳遞列表很有用,這種列表包含的可能是名字、數(shù)字或更復(fù)雜的對象(如字典)。將列表傳遞給函數(shù)后,函數(shù)就能直接訪問其內(nèi)容。下面使用函數(shù)來提高處理列表的效率。
假設(shè)有一個用戶列表,我們要問候其中的每位用戶。下面的示例將一個名字列表傳遞給一個名為greet_users()的函數(shù),這個函數(shù)問候列表中的每個人:
def greet_users(names): """向列表中的每位用戶都發(fā)出簡單的問候""" for name in names:msg = "Hello, " + name.title() + "!" print(msg)usernames = ['hannah', 'ty', 'margot'] greet_users(usernames)我們將greet_users()定義成接受一個名字列表,并將其存儲在形參names中。這個函數(shù)遍歷收到的列表,并對其中的每位用戶都打印一條問候語。然后我們定義了一個用戶列表——usernames,然后調(diào)用greet_users(),并將這個列表傳遞給它:
Hello, Hannah! Hello, Ty! Hello, Margot!輸出完全符合預(yù)期,每位用戶都看到了一條個性化的問候語。每當你要問候一組用戶時,都可調(diào)用這個函數(shù)。
在函數(shù)中修改列表
將列表傳遞給函數(shù)后,函數(shù)就可對其進行修改。在函數(shù)中對這個列表所做的任何修改都是永久性的,這讓你能夠高效地處理大量的數(shù)據(jù)。
來看一家為用戶提交的設(shè)計制作3D打印模型的公司。需要打印的設(shè)計存儲在一個列表中,打印后移到另一個列表中。下面是在不使用函數(shù)的情況下模擬這個過程的代碼:
# 首先創(chuàng)建一個列表,其中包含一些要打印的設(shè)計 unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron'] completed_models = [] # 模擬打印每個設(shè)計,直到?jīng)]有未打印的設(shè)計為止 # 打印每個設(shè)計后,都將其移到列表completed_models中 while unprinted_designs:current_design = unprinted_designs.pop()#模擬根據(jù)設(shè)計制作3D打印模型的過程 print("Printing model: " + current_design) completed_models.append(current_design) # 顯示打印好的所有模型 print("\nThe following models have been printed:") for completed_model in completed_models:print(completed_model)這個程序首先創(chuàng)建一個需要打印的設(shè)計列表,還創(chuàng)建一個名為completed_models的空列表, 每個設(shè)計打印都將移到這個列表中。
只要列表unprinted_designs中還有設(shè)計,while循環(huán)就模擬打印設(shè)計的過程:從該列表末尾刪除一個設(shè)計,將其存儲到變量current_design中,并顯示一條消息,指出正在打印當前的設(shè)計,再將該設(shè)計加入到列表completed_models中。循環(huán)結(jié)束后,顯示已打印的所有設(shè)計:
Printing model: dodecahedron Printing model: robot pendant Printing model: iphone case The following models have been printed: dodecahedron robot pendant iphone case為重新組織這些代碼,我們可編寫兩個函數(shù),每個都做一件具體的工作。大部分代碼都與原來相同,只是效率更高。第一個函數(shù)將負責(zé)處理打印設(shè)計的工作,而第二個將概述打印了哪些設(shè)計:
''' Python大型免費公開課,適合初學(xué)者入門 加QQ群:579817333 獲取學(xué)習(xí)資料及必備軟件。 ''' def print_models(unprinted_designs, completed_models):"""模擬打印每個設(shè)計,直到?jīng)]有未打印的設(shè)計為止打印每個設(shè)計后,都將其移到列表completed_models中"""while unprinted_designs:current_design = unprinted_designs.pop()# 模擬根據(jù)設(shè)計制作3D打印模型的過程print("Printing model: " + current_design)completed_models.append(current_design)def show_completed_models(completed_models): """顯示打印好的所有模型"""print("\nThe following models have been printed:") for completed_model in completed_models:print(completed_model) unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron'] completed_models = []print_models(unprinted_designs, completed_models) show_completed_models(completed_models)首先,我們定義了函數(shù)print_models(),它包含兩個形參:一個需要打印的設(shè)計列表和一個打印好的模型列表。
給定這兩個列表,這個函數(shù)模擬打印每個設(shè)計的過程:將設(shè)計逐個地從未 打印的設(shè)計列表中取出,并加入到打印好的模型列表中。
然后,我們定又義了函數(shù)show_completed_models(),它包含一個形參:打印好的模型列表。給定這個列表,函數(shù)show_completed_models()顯示打印出來的每個模型的名稱。
這個程序的輸出與未使用函數(shù)的版本相同,但組織更為有序。完成大部分工作的代碼都移到了兩個函數(shù)中,讓主程序更容易理解。只要看看主程序,你就知道這個程序的功能容易看清得多:
unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron'] completed_models = [] print_models(unprinted_designs, completed_models) show_completed_models(completed_models)我們創(chuàng)建了一個未打印的設(shè)計列表,還創(chuàng)建了一個空列表,用于存儲打印好的模型。接下來,由于我們已經(jīng)定義了兩個函數(shù),因此只需調(diào)用它們并傳入正確的實參即可。我們調(diào)用print_models()并向它傳遞兩個列表;像預(yù)期的一樣,print_models()模擬打印設(shè)計的過程。接下來,我們調(diào)用show_completed_models(),并將打印好的模型列表傳遞給它,讓其能夠指出打印了哪些模型。描述性的函數(shù)名讓別人閱讀這些代碼時也能明白,雖然其中沒有任何注釋。
相比于沒有使用函數(shù)的版本,這個程序更容易擴展和維護。如果以后需要打印其他設(shè)計,只需再次調(diào)用print_models()即可。如果我們發(fā)現(xiàn)需要對打印代碼進行修改,只需修改這些代碼一次,就能影響所有調(diào)用該函數(shù)的地方;與必須分別修改程序的多個地方相比,這種修改的效率更高。
這個程序還演示了這樣一種理念,即每個函數(shù)都應(yīng)只負責(zé)一項具體的工作。第一個函數(shù)打印每個設(shè)計,而第二個顯示打印好的模型;這優(yōu)于使用一個函數(shù)來完成兩項工作。編寫函數(shù)時,如果你發(fā)現(xiàn)它執(zhí)行的任務(wù)太多,請嘗試將這些代碼劃分到兩個函數(shù)中。別忘了,總是可以在一個函 數(shù)中調(diào)用另一個函數(shù),這有助于將復(fù)雜的任務(wù)劃分成一系列的步驟。
傳遞任意數(shù)量的實參
有時候,你預(yù)先不知道函數(shù)需要接受多少個實參,好在Python允許函數(shù)從調(diào)用語句中收集任意數(shù)量的實參。
例如,來看一個制作披薩的函數(shù),它需要接受很多配料,但你無法預(yù)先確定顧客要多少種配料。下面的函數(shù)只有一個形參*toppings,但不管調(diào)用語句提供了多少實參,這個形參都將它們統(tǒng)統(tǒng)收入囊中:
''' Python大型免費公開課,適合初學(xué)者入門 加QQ群:579817333 獲取學(xué)習(xí)資料及必備軟件。 ''' def make_pizza(*toppings): """打印顧客點的所有配料""" print(toppings)make_pizza('pepperoni')make_pizza('mushrooms', 'green peppers', 'extra cheese')形參名*toppings中的星號讓Python創(chuàng)建一個名為toppings的空元組,并將收到的所有值都封裝到這個元組中。函數(shù)體內(nèi)的print語句通過生成輸出來證明Python能夠處理使用一個值調(diào)用函數(shù)的情形,也能處理使用三個值來調(diào)用函數(shù)的情形。
它以類似的方式處理不同的調(diào)用,注意,Python將實參封裝到一個元組中,即便函數(shù)只收到一個值也如此:
('pepperoni',) ('mushrooms', 'green peppers', 'extra cheese')現(xiàn)在,我們可以將這條print語句替換為一個循環(huán),對配料列表進行遍歷,并對顧客點的披薩進行描述:
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')不管收到的是一個值還是三個值,這個函數(shù)都能妥善地處理:
Making a pizza with the following toppings: - pepperoni Making a pizza with the following toppings: - mushrooms - green peppers - extra cheese不管函數(shù)收到的實參是多少個,這種語法都管用。
將函數(shù)存儲在模塊中
函數(shù)的優(yōu)點之一是,使用它們可將代碼塊與主程序分離。通過給函數(shù)指定描述性名稱,可讓主程序容易理解得多。你還可以更進一步,將函數(shù)存儲在被稱為模塊的獨立文件中,再將模塊導(dǎo)入到主程序中。import語句允許在當前運行的程序文件中使用模塊中的代碼。
通過將函數(shù)存儲在獨立的文件中,可隱藏程序代碼的細節(jié),將重點放在程序的高層邏輯上。這還能讓你在眾多不同的程序中重用函數(shù)。將函數(shù)存儲在獨立文件中后,可與其他程序員共享這些文件而不是整個程序。知道如何導(dǎo)入函數(shù)還能讓你使用其他程序員編寫的函數(shù)庫。
導(dǎo)入模塊的方法有多種,下面對每種都作簡要的介紹。
導(dǎo)入整個模塊
要讓函數(shù)是可導(dǎo)入的,得先創(chuàng)建模塊。模塊是擴展名為.py的文件,包含要導(dǎo)入到程序中的代碼。下面來創(chuàng)建一個包含函數(shù)make_pizza()的模塊。為此,我們將文件pizza.py中除函數(shù)make_pizza()之外的其他代碼都刪除:
''' Python大型免費公開課,適合初學(xué)者入門 加QQ群:579817333 獲取學(xué)習(xí)資料及必備軟件。 ''' def make_pizza(size, *toppings):"""概述要制作的比薩"""print("\nMaking a " + str(size) + "-inch pizza with the following toppings:")for topping in toppings:print("- " + topping)接下來,我們在pizza.py所在的目錄中創(chuàng)建另一個名為making_pizzas.py的文件,這個文件導(dǎo)入剛創(chuàng)建的模塊,再調(diào)用make_pizza()兩次:
import pizza pizza.make_pizza(16, 'pepperoni') pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')Python讀取這個文件時,代碼行import pizza讓Python打開文件pizza.py,并將其中的所有函數(shù)都復(fù)制到這個程序中。你看不到復(fù)制的代碼,因為這個程序運行時,Python在幕后復(fù)制這些代碼。你只需知道,在making_pizzas.py中,可以使用pizza.py中定義的所有函數(shù)。
要調(diào)用被導(dǎo)入的模塊中的函數(shù),可指定導(dǎo)入的模塊的名稱pizza和函數(shù)名make_pizza(),并用句點分隔它們。這些代碼的輸出與沒有導(dǎo)入模塊的原始程序相同:
Making a 16-inch pizza with the following toppings: - pepperoni Making a 12-inch pizza with the following toppings: - mushrooms - green peppers - extra cheese這就是一種導(dǎo)入方法:只需編寫一條import語句并在其中指定模塊名,就可在程序中使用該模塊中的所有函數(shù)。如果你使用這種import語句導(dǎo)入了名為module_name.py的整個模塊,就可使用下面的語法來使用其中任何一個函數(shù):
module_name.function_name()導(dǎo)入特定的函數(shù)
你還可以導(dǎo)入模塊中的特定函數(shù),這種導(dǎo)入方法的語法如下:
from module_name import function_name通過用逗號分隔函數(shù)名,可根據(jù)需要從模塊中導(dǎo)入任意數(shù)量的函數(shù):
from module_name import function_0, function_1, function_2對于前面的making_pizzas.py示例,如果只想導(dǎo)入要使用的函數(shù),代碼將類似于下面這樣:
from pizza import make_pizza make_pizza(16, 'pepperoni') make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')若使用這種語法,調(diào)用函數(shù)時就無需使用句點。由于我們在import語句中顯式地導(dǎo)入了函數(shù)make_pizza(),因此調(diào)用它時只需指定其名稱。
使用as給函數(shù)指定別名
如果要導(dǎo)入的函數(shù)的名稱可能與程序中現(xiàn)有的名稱沖突,或者函數(shù)的名稱太長,可指定簡短而獨一無二的別名——函數(shù)的另一個名稱,類似于外號。要給函數(shù)指定這種特殊外號,需要在導(dǎo)入它時這樣做。
下面給函數(shù)make_pizza()指定了別名mp()。這是在import語句中使用make_pizza as mp實現(xiàn)的,關(guān)鍵字as將函數(shù)重命名為你提供的別名:
''' Python大型免費公開課,適合初學(xué)者入門 加QQ群:579817333 獲取學(xué)習(xí)資料及必備軟件。 ''' from pizza import make_pizza as mp mp(16, 'pepperoni') mp(12, 'mushrooms', 'green peppers', 'extra cheese')上面的import語句將函數(shù)make_pizza()重命名為mp();在這個程序中,每當需要調(diào)用make_pizza()時,都可簡寫成mp(),而Python將運行make_pizza()中的代碼,這可避免與這個程序可能包含的函數(shù)make_pizza()混淆。指定別名的通用語法如下:
from module_name import function_name as fn使用as給模塊指定別名
你還可以給模塊指定別名。通過給模塊指定簡短的別名(如給模塊pizza指定別名p),讓你能夠更輕松地調(diào)用模塊中的函數(shù)。相比于pizza.make_pizza(),p.make_pizza()更為簡潔:
import pizza as p p.make_pizza(16, 'pepperoni') p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')上述import語句給模塊pizza指定了別名p,但該模塊中所有函數(shù)的名稱都沒變。調(diào)用函數(shù)make_pizza()時,可編寫代碼p.make_pizza()而不是pizza.make_pizza(),這樣不僅能使代碼更簡潔,還可以讓你不再關(guān)注模塊名,而專注于描述性的函數(shù)名。這些函數(shù)名明確地指出了函數(shù)的功能,對理解代碼而言,它們比模塊名更重要。 給模塊指定別名的通用語法如下:
import module_name as mn導(dǎo)入模塊中的所有函數(shù)
使用星號(*)運算符可讓Python導(dǎo)入模塊中的所有函數(shù):
from pizza import * make_pizza(16, 'pepperoni') make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese')import語句中的星號讓Python將模塊pizza中的每個函數(shù)都復(fù)制到這個程序文件中。由于導(dǎo)入了每個函數(shù),可通過名稱來調(diào)用每個函數(shù),而無需使用句點表示法。然而,使用并非自己編寫的大型模塊時,最好不要采用這種導(dǎo)入方法:如果模塊中有函數(shù)的名稱與你的項目中使用的名稱相同,可能導(dǎo)致意想不到的結(jié)果:Python可能遇到多個名稱相同的函數(shù)或變量,進而覆蓋函數(shù),而不是分別導(dǎo)入所有的函數(shù)。
最佳的做法是,要么只導(dǎo)入你需要使用的函數(shù),要么導(dǎo)入整個模塊并使用句點表示法。這能讓代碼更清晰,更容易閱讀和理解。這里之所以介紹這種導(dǎo)入方法,只是想讓你在閱讀別人編寫 的代碼時,如果遇到類似于下面的import語句,能夠理解它們:
from module_name import *函數(shù)編寫指南
編寫函數(shù)時,需要牢記幾個細節(jié)。應(yīng)給函數(shù)指定描述性名稱,且只在其中使用小寫字母和下 劃線。描述性名稱可幫助你和別人明白代碼想要做什么。給模塊命名時也應(yīng)遵循上述約定。
每個函數(shù)都應(yīng)包含簡要地闡述其功能的注釋,該注釋應(yīng)緊跟在函數(shù)定義后面,并采用文檔字 符串格式。
文檔良好的函數(shù)讓其他程序員只需閱讀文檔字符串中的描述就能夠使用它:他們完全 可以相信代碼如描述的那樣運行;只要知道函數(shù)的名稱、需要的實參以及返回值的類型,就能在 自己的程序中使用它。
給形參指定默認值時,等號兩邊不要有空格:
def function_name(parameter_0, parameter_1='default value')對于函數(shù)調(diào)用中的關(guān)鍵字實參,也應(yīng)遵循這種約定:
function_name(value_0, parameter_1='value')官方建議代碼行的長度不要超過79字符,這樣只要編輯器窗口適中,就能看到整行代碼。如果形參很多,導(dǎo)致函數(shù)定義的長度超過了79字符,可在函數(shù)定義中輸入左括號后按回車鍵,并在下一行按兩次Tab鍵,從而將形參列表和只縮進一 層的函數(shù)體區(qū)分開來。
大多數(shù)編輯器都會自動對齊后續(xù)參數(shù)列表行,使其縮進程度與你給第一個參數(shù)列表行指定的 縮進程度相同:
def function_name(parameter_0, parameter_1, parameter_2, parameter_3, parameter_4, parameter_5):function body...如果程序或模塊包含多個函數(shù),可使用兩個空行將相鄰的函數(shù)分開,這樣將更容易知道前一 個函數(shù)在什么地方結(jié)束,下一個函數(shù)從什么地方開始。所有的import語句都應(yīng)放在文件開頭,唯一例外的情形是,在文件開頭使用了注釋來描述整個程序。
總結(jié)
以上是生活随笔為你收集整理的python函数的高级用法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python处理字符串和列表元组的小技巧
- 下一篇: Python3 中的最大整数和最大浮点数