|
前面講了很多內(nèi)容都是關(guān)于python的變量,數(shù)據(jù)結(jié)構(gòu),下面我們來(lái)談一談python的函數(shù)。python里的函數(shù)知識(shí)點(diǎn)大概分為基礎(chǔ)的定義使用,作用域和參數(shù)傳遞,高級(jí)用法,其中參數(shù)傳遞最為靈活,作用域最為繞人. 函數(shù)其實(shí)是對(duì)程序邏輯進(jìn)行結(jié)構(gòu)化或者過(guò)程化的一種編程方法,把整塊的代碼巧妙的隔離成易于管理的小塊,是最基本的一種代碼抽象的方式。 python函數(shù)是用def關(guān)鍵字定義的:
今天我們先來(lái)說(shuō)一說(shuō)里面的一些小花招,算是給初學(xué)者的開(kāi)胃菜,為后面正式講函數(shù)熱熱身: 1.Python函數(shù)可以返回多個(gè)值 一般的編程語(yǔ)言比如c,c++,java,一般返回的都是一個(gè)值,python可以返回多個(gè)值(perl其實(shí)也可以),因?yàn)橛械臅r(shí)候我們除了需要函數(shù)返回計(jì)算的結(jié)果,我們還需要返回一些操作的狀態(tài),看個(gè)簡(jiǎn)單的例子你就明白了 : 這個(gè)getHtmlResponse()函數(shù)可以返回多個(gè)值,第一值是返回處理的狀態(tài)True or false,第二值是msg,有的時(shí)候我們需要先判斷狀態(tài),若true 就不管了,若是false再進(jìn)一步處理. 這樣的場(chǎng)景下用函數(shù)返回多個(gè)值這個(gè)特性很容易搞定.原理其實(shí)就是函數(shù)返回了一個(gè)元組,然后把結(jié)果賦值給多個(gè)變量。 說(shuō)到這里,我穿插一個(gè)小技巧,我的時(shí)候我們希望丟棄掉一些返回值, 我們可以用_搞定(用一個(gè)幾乎用不到的變量名,來(lái)作為要丟棄的值的名稱) def getRoomData(): return 'class room is 203',1000,'2016-10-06' _,price,_=getData() print price >>1000 2.盡量用異常表示特殊情況,不要返回None python函數(shù)若你什么都不return,默認(rèn)返回None,很容易忽視這一點(diǎn) def addFun(a,b): sum=a+b print addFun(10,20) >>None 有的同學(xué)說(shuō)我寫函數(shù)代碼,會(huì)記得加上None,但是有的時(shí)候返回None也會(huì)讓你誤解,不好處理,你不信我們看下面一個(gè)例子: 原因是當(dāng)分子為0的時(shí)候,計(jì)算結(jié)果為0,那這個(gè)結(jié)果去做條件判斷時(shí),會(huì)出現(xiàn)問(wèn)題,會(huì)弄巧成拙。其實(shí)你返回None是有特殊意義的,是為了判斷分母為0. 解決這個(gè)問(wèn)題有兩個(gè)辦法:第一個(gè)是把返回值拆成兩部分,返回一個(gè)元組,第一個(gè)元素是操作是否成功,第二個(gè)是運(yùn)行結(jié)果,改成如下: def divide(a,b): try: return True,a/b except ZeroDivisionError: return False,None print (divide(0,10)) >>(True, 0) 第二個(gè)好的辦法是:根本不返回None,直接拋異常給上一級(jí),使得調(diào)用者必須應(yīng)對(duì)它,好我們來(lái)改一下代碼看看: #異常部分后面會(huì)講,valueError是異常中的一種,表示傳給函數(shù)的參數(shù)類型不正確
3.匿名函數(shù) python除了def語(yǔ)句之外,還提供了一中懶人專用的函數(shù)叫做lambda,有點(diǎn)LISP語(yǔ)言的風(fēng)格(LISP是一個(gè)非常著名的黑客語(yǔ)言).所以稱為lambda匿名函數(shù),其實(shí)就想def一樣,這個(gè)表達(dá)式創(chuàng)建了一個(gè)能夠調(diào)用的函數(shù),它其實(shí)是返回一個(gè)函數(shù)而不是像傳統(tǒng)的函數(shù)賦值給一個(gè)變量名,所以一般都是在一種行內(nèi)進(jìn)行使用. 形式: lambda arg1,arg2...argN:expression using arg
作為一個(gè)表達(dá)式,經(jīng)常在列表中或者函數(shù)中調(diào)用,能夠出現(xiàn)在python語(yǔ)法不允許出現(xiàn)def的地方.此外做為一個(gè)表達(dá)式lambda返回了一個(gè)值(新的函數(shù)),可以選擇性的賦值給一個(gè)變量名。
lambda的主體簡(jiǎn)單的就像放在def主體的return 里的代碼一樣,寫成一個(gè)表達(dá)式,lambda通常比def功能要小,只能封裝一些有限的邏輯,lambda為簡(jiǎn)單任務(wù)而生,def則處理更大更復(fù)雜的任務(wù). 對(duì)比一下吧:
def addFunc(x,y,z): return x+y+z print addFunc(1,2,3) >>6
f=lambda x,y,z:x+y+z print f(1,2,3) >>6 在比如在排序?qū)?shù)據(jù)整理時(shí)經(jīng)常用到: names=['David Bea','Zrian Aones','Raymond Het'] print sorted(names,key=lambda name:name.split()[-1].lower()) >>['Zrian Aones', 'David Bea', 'Raymond Het'] 也許懶惰也是推進(jìn)人類進(jìn)步的一大利器,當(dāng)年因?yàn)閼卸柘覦os太麻煩才有了win,當(dāng)年的手機(jī)系統(tǒng)因?yàn)閼卸柘M挥面I盤直接手點(diǎn)點(diǎn)多好才有了觸摸屏,因?yàn)閼卸钁械拇蜃植磐七M(jìn)了語(yǔ)音識(shí)別. 4.警惕默認(rèn)參數(shù)的潛在問(wèn)題 最后一個(gè)花招是很具有迷惑性的,一定要看仔細(xì),一般我們?cè)诤瘮?shù)參數(shù)傳遞的時(shí)候,希望用一種非靜態(tài)的類型來(lái)作為關(guān)鍵字的默認(rèn)值,比如我們經(jīng)常會(huì)有打印日志消息的函數(shù): 奇怪兩條消息戳是一樣的,這是因?yàn)閐atetime.datetime.now()只執(zhí)行了一次,也就是說(shuō)在函數(shù)定義的時(shí)候執(zhí)行了一次。參數(shù)的默認(rèn)值會(huì)在每一個(gè)模塊加載進(jìn)來(lái)的時(shí)候求出,一旦這段模塊加載進(jìn)來(lái)了,參數(shù)的默認(rèn)值就很固定了,程序不會(huì)再出執(zhí)行datetime.datetime.now() 是不是覺(jué)得很冤枉,明明想動(dòng)態(tài)的一下的,反而變成了靜靜~~ 腫么辦 這里有一個(gè)小技巧,在Python中若你想動(dòng)態(tài)實(shí)現(xiàn)默認(rèn)值,習(xí)慣把默認(rèn)值改成None,然后加一些注釋,看代碼吧: 現(xiàn)在兩條消息的時(shí)間戳就不同了,如果參數(shù)的實(shí)際默認(rèn)值是可變類型,切記切記用None作為形式上的默認(rèn)值. |
|
|
來(lái)自: Four兄 > 《Python筆記》