眾所周知,熟悉Python的小伙們接觸最多的就是函數(shù),函數(shù)是組織好的、可重復(fù)使用的、用來實(shí)現(xiàn)單一或相關(guān)聯(lián)功能的代碼段。
函數(shù)能提高應(yīng)用的模塊性和代碼的重復(fù)利用率。除了Python提供了許多內(nèi)建函數(shù),比如print()。而我們接觸最頻繁的就是用戶自定義函數(shù)。
函數(shù)定義
函數(shù)定義要素:
-
def關(guān)鍵詞,后接函數(shù)標(biāo)識(shí)符名稱和圓括號(hào) ()。
-
參數(shù),任何傳入?yún)?shù)和自變量必須放在圓括號(hào)中間,圓括號(hào)之間可以用于定義參數(shù)。
-
函數(shù)的第一行語句可以選擇性地使用文檔字符串—用于存放函數(shù)說明。
-
函數(shù)內(nèi)容以冒號(hào): 起始,并且縮進(jìn)。
-
return [表達(dá)式] 結(jié)束函數(shù),選擇性地返回一個(gè)值給調(diào)用方,不帶表達(dá)式的 return 相當(dāng)于返回 None。
不定長參數(shù)
函數(shù)更多地使用場景是根據(jù)動(dòng)態(tài)的輸入返回動(dòng)態(tài)的結(jié)果,這樣入?yún)⒈仨毷亲兞俊6雲(yún)⒌念愋鸵彩怯卸喾N的,例如定長和不定長參數(shù),定長參數(shù)大家接觸的最多,不做贅述,簡單介紹下不定長參數(shù):
有時(shí),你可能需要一個(gè)函數(shù)能處理比當(dāng)初聲明時(shí)更多的參數(shù),這些參數(shù)叫做不定長參數(shù),和定長參數(shù)不同,聲明時(shí)不會(huì)命名。基本語法如下:
def functionname([formal_args,] *var_args_tuple ):
"函數(shù)_文檔字符串"
function_suite
return [expression]
注意:加了星號(hào) * 的參數(shù)會(huì)以元組(tuple)的形式導(dǎo)入,存放所有未命名的變量參數(shù)。如果在函數(shù)調(diào)用時(shí)沒有指定參數(shù),它就是一個(gè)空元組。
# 函數(shù)說明
def printinfo(arg1, *vartuple):
"打印任何傳入的參數(shù)"
print("輸出: ")
print(arg1)
print(vartuple)
# 調(diào)用printinfo 函數(shù)
printinfo(70, 60, 50)
printinfo(70)
輸出:
70
(60,50)
輸出:
70
()
還有一種就是參數(shù)帶兩個(gè)星號(hào) **基本語法如下:
def functionname([formal_args,] **var_args_dict ):
"函數(shù)_文檔字符串"
function_suite
return [expression]
函數(shù)開發(fā)四條原則
為了使代碼更好的復(fù)用和最小程度的代碼冗余,掌握函數(shù)開發(fā)的四個(gè)原則尤為重要。

這個(gè)函數(shù)實(shí)現(xiàn)了自動(dòng)根據(jù)播單id,下載MP3音頻的功能。可以分為三個(gè)步驟:
-
請(qǐng)求播單,得到播單響應(yīng)
-
提取播單中MP3地址
-
下載MP3音頻并保存到本地
原則一:函數(shù)設(shè)計(jì)要盡量小,嵌套層次不宜過深。
所謂小,就是盡量避免過長函數(shù),因?yàn)檫@樣不需要上下拉動(dòng)滾動(dòng)條就能獲得整體感觀,而不是來回翻動(dòng)屏幕去尋找某個(gè)變量或者某條邏輯判斷等。函數(shù)中需要用到if、elif、while、for等循環(huán)語句的地方,盡量不要嵌套過深,最好能控制在3層以內(nèi)。相信很多人有過這樣的經(jīng)歷:為了弄清楚哪段代碼屬于內(nèi)部嵌套,哪段屬于中間層次的嵌套,哪段屬于更外一層”
原則二:函數(shù)聲明應(yīng)該做到合理、簡單且參數(shù)不易太多。
試想,當(dāng)你看到一個(gè)函數(shù)名和其實(shí)現(xiàn)邏輯不一致的時(shí)候作何感想。函數(shù)命名應(yīng)“反映其大體功能外,參數(shù)的設(shè)計(jì)也應(yīng)該簡潔明了,參數(shù)個(gè)數(shù)不宜太多。參數(shù)太多帶來的弊端是:調(diào)用者需要花費(fèi)更多的時(shí)間去理解每個(gè)參數(shù)的意思,測試人員需要花費(fèi)更多的精力來設(shè)計(jì)測試用例,以確保參數(shù)的組合能夠有合理的輸出,這使覆蓋測試的難度大大增加。
最近在看《像火箭科學(xué)家一樣思考》一書【強(qiáng)推此書】,里面就有講到對(duì)復(fù)雜與簡單的看法,就函數(shù)而言,每增加一個(gè)參數(shù),就增加函數(shù)自身可能出錯(cuò)的風(fēng)險(xiǎn)。
原則三:函數(shù)參數(shù)設(shè)計(jì)應(yīng)該考慮向下兼容。
這個(gè)對(duì)于經(jīng)常做項(xiàng)目的同學(xué)應(yīng)該更有體感,敏捷開發(fā)模式下,項(xiàng)目迭代更快,對(duì)于比較大的項(xiàng)目,可能存在多項(xiàng)目并行的情況,一套代碼由多條線并行開發(fā)。那么,這種模式下,你設(shè)計(jì)的函數(shù) 就必須 要預(yù)見到未來可能會(huì)擴(kuò)展到的功能。例如一個(gè)大項(xiàng)目拆分成多個(gè)小項(xiàng)目迭代完成,這樣你在設(shè)計(jì)函數(shù)初期就必須考慮到未來函數(shù)升級(jí)需要兼顧到地方,為未來升級(jí)留下“口子”,不致于每次迭代都要打改動(dòng)。
例如本案例,后面要求將下載的音頻按類目保存到不同的文件夾下面,那么這樣就必須根據(jù)MP3的地址動(dòng)態(tài)選擇要存放的文件夾,所以函數(shù)入?yún)⒕捅仨氃黾右粋€(gè)目錄的參數(shù),試想,如果在本代碼上改動(dòng),影響范圍有多大呢?
當(dāng)然解法也有,就是在函數(shù)設(shè)計(jì)之初就預(yù)留不定長參數(shù)或默認(rèn)參數(shù),以備不時(shí)之需。
def DownLoadMp3(id, dir=social):
原則四:函數(shù)職責(zé)盡可能單一。
要保證一個(gè)函數(shù)只做一件事,就要盡量保證抽象層級(jí)的一致性,所有的語句盡量在一個(gè)粒度上。同時(shí)在一個(gè)函數(shù)中處理多件事情也不利于代碼的重用。本案例的改進(jìn)版,可以將代碼拆分成三部分:信息提取、下載、流程編排。具體實(shí)現(xiàn)如下:
# 1.獲取音頻Mp3信息
def getMp3Response(id):
url = "http://fm.xinli001.com/broadcast"
querystring = {"pk": id}
headers = {
'accept': "application/json, text/javascript, */*; q=0.01",
'x-requested-with': "XMLHttpRequest",
'user-agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36",
'cache-control': "no-cache",
'postman-token': "3a95a7d6-5834-f6ae-5678-82b496bf9c71"
}
response = requests.request("GET", url, headers=headers, params=querystring)
print(response.text)
try:
res = json.loads(response.text)
except:
res = ''
return res
# 2.保存為MP3, 保存到特定文件夾下面:文件夾以專輯名字命名
def saveAudio(url, album, filename):
filepath = os.getcwd()+'/mp3/'+album
if os.path.exists(filepath):
mp3 = os.path.join(filepath + '/', '' + filename + '.mp3')
if url == '':
print('the url is NUll, pass')
else:
urllib.request.urlretrieve(url, mp3, cbk)
print(filename+'下載完畢')
else:
os.makedirs(filepath)
mp3 = os.path.join(filepath + '/', '' + filename + '.mp3')
if url == '':
print('the url is NUll, pass')
else:
urllib.request.urlretrieve(url, mp3, cbk)
print(filename+' 下載完畢')
# 3.main函數(shù)實(shí)現(xiàn)流程編排
def main():
album = '壹心理'
for id in range(38, 99395999):
res = getMp3Response(id)
if res:
try:
title = str(id) + '-' + res.get('data').get('title')
url = res.get('data').get('url')
saveAudio(url, album, title)
except:
print(str(res) + '為空')
本文來自博客園,作者:前進(jìn)者-影子,轉(zhuǎn)載請(qǐng)注明原文鏈接:http://www.rzrgm.cn/yingzili/p/16654919.html
浙公網(wǎng)安備 33010602011771號(hào)